@@ -3377,87 +3377,16 @@ def update(self):
3377
3377
)
3378
3378
3379
3379
3380
- class _PerfMetricsSendData (DashboardComponent ):
3381
- @log_errors
3382
- def __init__ (self , scheduler , ** kwargs ):
3383
- self .scheduler = scheduler
3384
- self .data = defaultdict (list )
3385
- self .source = ColumnDataSource (data = dict ())
3386
- self .substantial_change = False
3387
- self .init_root ()
3388
-
3389
- def init_root (self ):
3390
- self .fig = figure ()
3391
- self .root = row ([self .fig ])
3392
-
3393
- @without_property_validation
3394
- @log_errors
3395
- def update (self ):
3396
- items = self .scheduler .cumulative_worker_metrics .items ()
3397
- items = (
3398
- (k , v )
3399
- for k , v in items
3400
- if isinstance (k , tuple ) and k [0 ] == "get-data" and k [- 1 ] == "seconds"
3401
- )
3402
- for (_type , operation , _freq ), val in items :
3403
- if operation not in self .data ["operation" ]:
3404
- self .substantial_change = True
3405
- self .data ["operation" ].append (operation )
3406
-
3407
- idx = self .data ["operation" ].index (operation )
3408
- while idx >= len (self .data ["value" ]):
3409
- self .data ["value" ].append (float ("NaN" ))
3410
- self .data ["value" ][idx ] = val
3411
-
3412
- self .data ["text" ] = [format_time (n ) for n in self .data ["value" ]]
3413
- self .data ["angle" ] = [
3414
- value / sum (self .data ["value" ]) * 2 * math .pi
3415
- for value in self .data ["value" ]
3416
- ]
3417
- self .data ["color" ] = small_palettes ["YlGnBu" ].get (
3418
- len (self .data ["operation" ]), []
3419
- )
3420
-
3421
- if self .data :
3422
- self .source .data = dict (self .data )
3423
- fig = figure (
3424
- height = 500 ,
3425
- title = "Send data, by activity" ,
3426
- tools = "hover" ,
3427
- tooltips = "@{operation}: @text" ,
3428
- x_range = (- 0.5 , 1.0 ),
3429
- )
3430
- fig .wedge (
3431
- x = 0 ,
3432
- y = 1 ,
3433
- radius = 0.4 ,
3434
- start_angle = cumsum ("angle" , include_zero = True ),
3435
- end_angle = cumsum ("angle" ),
3436
- line_color = "white" ,
3437
- fill_color = "color" ,
3438
- legend_field = "operation" ,
3439
- source = self .source ,
3440
- )
3441
- fig .axis .axis_label = None
3442
- fig .axis .visible = False
3443
- fig .grid .grid_line_color = None
3444
-
3445
- if self .substantial_change :
3446
- self .root .children [0 ] = fig
3447
- self .substantial_change = False
3448
- else :
3449
- self .fig = fig
3450
-
3451
-
3452
- class _PerfMetricsExecutionByPrefixAndActivity (DashboardComponent ):
3380
+ class FinePerformanceMetrics (DashboardComponent ):
3453
3381
"""
3454
- Stacked bar-chart displaying breakdown of function execution times
3455
- between de/serialization, thread-non/cpu, etc.
3382
+ The main overview of the Fine Performance Metrics page.
3456
3383
"""
3457
3384
3458
3385
@log_errors
3459
3386
def __init__ (self , scheduler , ** kwargs ):
3460
3387
self .scheduler = scheduler
3388
+ self .senddata = defaultdict (list )
3389
+ self .sendsource = ColumnDataSource (data = dict ())
3461
3390
self .data = defaultdict (list )
3462
3391
self .source = ColumnDataSource (data = dict ())
3463
3392
self .piechart_source = ColumnDataSource (data = dict ())
@@ -3480,10 +3409,12 @@ def handle_toggle(_toggle):
3480
3409
self .toggle .on_click (handle_toggle )
3481
3410
self .barchart = figure ()
3482
3411
self .piechart = figure ()
3412
+ self .senddata_piechart = figure ()
3483
3413
self .root = column (
3484
3414
self .function_selector ,
3485
3415
self .toggle ,
3486
3416
row ([self .piechart , self .barchart ]),
3417
+ row ([self .senddata_piechart ]),
3487
3418
sizing_mode = "scale_width" ,
3488
3419
)
3489
3420
@@ -3493,35 +3424,53 @@ def update(self):
3493
3424
items = (
3494
3425
(k , v )
3495
3426
for k , v in self .scheduler .cumulative_worker_metrics .items ()
3496
- if isinstance (k , tuple )
3497
- and k [0 ] == "execute"
3498
- and k [- 1 ] in ("bytes" , "seconds" )
3499
- )
3500
- for (_type , function_name , operation , freq ), val in items :
3501
- if operation not in self .operations :
3502
- self .substantial_change = True
3503
- self .operations .append (operation )
3504
-
3505
- if function_name not in self .data ["functions" ]:
3506
- self .substantial_change = True
3507
- self .function_selector .options .append (function_name )
3508
- self .data ["functions" ].append (function_name )
3509
- self .data ["timestamp" ].append (datetime .utcnow ())
3510
- idx = self .data ["functions" ].index (function_name )
3511
-
3512
- # Some function/operation combos missing, so need to keep columns aligned
3513
- for op in self .operations :
3514
- while len (self .data [f"{ op } _value" ]) != len (self .data ["functions" ]):
3515
- self .data [f"{ op } _value" ].append (0 )
3516
- self .data [f"{ op } _bytes" ].append (0 )
3517
- self .data [f"{ op } _text" ].append ("" )
3518
-
3519
- if freq == "seconds" :
3520
- self .data [f"{ operation } _text" ][idx ] = format_time (val )
3521
- self .data [f"{ operation } _value" ][idx ] = val
3522
- elif freq == "bytes" :
3523
- self .data [f"{ operation } _text" ][idx ] = format_bytes (val )
3524
- self .data [f"{ operation } _bytes" ][idx ] = val
3427
+ if isinstance (k , tuple ) and k [- 1 ] in ("bytes" , "seconds" )
3428
+ )
3429
+ for (type , * parts ), val in items :
3430
+ if type == "get-data" :
3431
+ operation , freq = parts
3432
+ if operation not in self .senddata ["operation" ]:
3433
+ self .substantial_change = True
3434
+ self .senddata ["operation" ].append (operation )
3435
+
3436
+ idx = self .senddata ["operation" ].index (operation )
3437
+ while idx >= len (self .senddata [f"{ operation } _value" ]):
3438
+ self .senddata [f"{ operation } _bytes" ].append (0 )
3439
+ self .senddata [f"{ operation } _value" ].append (0 )
3440
+ self .senddata [f"{ operation } _text" ].append (0 )
3441
+ if freq == "bytes" :
3442
+ self .senddata [f"{ operation } _text" ][idx ] = format_bytes (val )
3443
+ self .senddata [f"{ operation } _bytes" ][idx ] = val
3444
+ elif freq == "seconds" :
3445
+ self .senddata [f"{ operation } _text" ][idx ] = format_time (val )
3446
+ self .senddata [f"{ operation } _value" ][idx ] = val
3447
+
3448
+ elif type == "execute" :
3449
+ function_name , operation , freq = parts
3450
+ if operation not in self .operations :
3451
+ self .substantial_change = True
3452
+ self .operations .append (operation )
3453
+
3454
+ if function_name not in self .data ["functions" ]:
3455
+ self .substantial_change = True
3456
+ self .function_selector .options .append (function_name )
3457
+ self .data ["functions" ].append (function_name )
3458
+ self .data ["timestamp" ].append (datetime .utcnow ())
3459
+ idx = self .data ["functions" ].index (function_name )
3460
+
3461
+ # Some function/operation combos missing, so need to keep columns aligned
3462
+ for op in self .operations :
3463
+ while len (self .data [f"{ op } _value" ]) != len (self .data ["functions" ]):
3464
+ self .data [f"{ op } _value" ].append (0 )
3465
+ self .data [f"{ op } _bytes" ].append (0 )
3466
+ self .data [f"{ op } _text" ].append ("" )
3467
+
3468
+ if freq == "seconds" :
3469
+ self .data [f"{ operation } _text" ][idx ] = format_time (val )
3470
+ self .data [f"{ operation } _value" ][idx ] = val
3471
+ elif freq == "bytes" :
3472
+ self .data [f"{ operation } _text" ][idx ] = format_bytes (val )
3473
+ self .data [f"{ operation } _bytes" ][idx ] = val
3525
3474
3526
3475
data = self .data .copy ()
3527
3476
@@ -3623,6 +3572,52 @@ def update(self):
3623
3572
self .substantial_change = True
3624
3573
self .source .data = dict (data )
3625
3574
3575
+ senddata = dict ()
3576
+ senddata ["operation" ] = self .senddata ["operation" ]
3577
+ senddata ["value" ] = [
3578
+ (sum (self .senddata [f"{ op } _{ 'bytes' if show_bytes else 'value' } " ]))
3579
+ for op in self .senddata ["operation" ]
3580
+ ]
3581
+ senddata ["text" ] = [
3582
+ format_bytes (n ) if show_bytes else format_time (n ) for n in senddata ["value" ]
3583
+ ]
3584
+ senddata ["angle" ] = [
3585
+ (
3586
+ (
3587
+ sum (self .senddata [f"{ op } _{ 'bytes' if show_bytes else 'value' } " ])
3588
+ / sum (senddata ["value" ])
3589
+ )
3590
+ if sum (senddata ["value" ])
3591
+ else 0.0
3592
+ )
3593
+ * 2
3594
+ * math .pi
3595
+ for op in senddata ["operation" ]
3596
+ ]
3597
+ senddata ["color" ] = small_palettes ["YlGnBu" ].get (len (senddata ["operation" ]), [])
3598
+ self .sendsource .data = senddata
3599
+ senddata_piechart = figure (
3600
+ height = 500 ,
3601
+ title = "Send data, by activity" ,
3602
+ tools = "hover" ,
3603
+ tooltips = "@{operation}: @text" ,
3604
+ x_range = (- 0.5 , 1.0 ),
3605
+ )
3606
+ senddata_piechart_renderers = senddata_piechart .wedge (
3607
+ x = 0 ,
3608
+ y = 1 ,
3609
+ radius = 0.4 ,
3610
+ start_angle = cumsum ("angle" , include_zero = True ),
3611
+ end_angle = cumsum ("angle" ),
3612
+ line_color = "white" ,
3613
+ fill_color = "color" ,
3614
+ legend_field = "operation" ,
3615
+ source = self .sendsource ,
3616
+ )
3617
+ senddata_piechart .axis .axis_label = None
3618
+ senddata_piechart .axis .visible = False
3619
+ senddata_piechart .grid .grid_line_color = None
3620
+
3626
3621
# Show total number of functions to choose from
3627
3622
self .function_selector .title = (
3628
3623
f"Filter by function ({ len (self .function_selector .options )} ):"
@@ -3631,39 +3626,16 @@ def update(self):
3631
3626
# replacing the child causes small blips if done every iteration vs updating renderers
3632
3627
# but it's needed when new functions and/or operations show up to rerender plot
3633
3628
if self .substantial_change :
3634
- self .root .children [- 1 ].children [0 ] = barchart
3635
- self .root .children [- 1 ].children [1 ] = piechart
3629
+ self .root .children [- 2 ].children [0 ] = barchart
3630
+ self .root .children [- 2 ].children [1 ] = piechart
3631
+ if self .senddata :
3632
+ self .root .children [- 1 ].children [0 ] = senddata_piechart
3636
3633
self .substantial_change = False
3637
3634
else :
3638
3635
self .barchart .renderers = renderers
3639
3636
self .piechart .renderers = [piechart_renderers ]
3640
-
3641
-
3642
- class FinePerformanceMetrics (DashboardComponent ):
3643
- """
3644
- The main overview of the Fine Performance Metrics page.
3645
- """
3646
-
3647
- @log_errors
3648
- def __init__ (self , scheduler , ** kwargs ):
3649
- self .scheduler = scheduler
3650
-
3651
- self .metrics_by_prefix_and_activity = _PerfMetricsExecutionByPrefixAndActivity (
3652
- scheduler , ** kwargs
3653
- )
3654
- self .metrics_send_data = _PerfMetricsSendData (scheduler , ** kwargs )
3655
- self .root = column (
3656
- [
3657
- self .metrics_by_prefix_and_activity .root ,
3658
- self .metrics_send_data .root ,
3659
- ]
3660
- )
3661
-
3662
- @without_property_validation
3663
- @log_errors
3664
- def update (self ):
3665
- self .metrics_by_prefix_and_activity .update ()
3666
- self .metrics_send_data .update ()
3637
+ if self .senddata :
3638
+ self .senddata_piechart .renderers = [senddata_piechart_renderers ]
3667
3639
3668
3640
3669
3641
class Contention (DashboardComponent ):
0 commit comments