Skip to content

Commit d3caebd

Browse files
committed
Merge fine metrics classes, all plots update on bytes toggle [skip ci]
1 parent a4feff5 commit d3caebd

File tree

1 file changed

+105
-133
lines changed

1 file changed

+105
-133
lines changed

distributed/dashboard/components/scheduler.py

Lines changed: 105 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -3377,87 +3377,16 @@ def update(self):
33773377
)
33783378

33793379

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):
34533381
"""
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.
34563383
"""
34573384

34583385
@log_errors
34593386
def __init__(self, scheduler, **kwargs):
34603387
self.scheduler = scheduler
3388+
self.senddata = defaultdict(list)
3389+
self.sendsource = ColumnDataSource(data=dict())
34613390
self.data = defaultdict(list)
34623391
self.source = ColumnDataSource(data=dict())
34633392
self.piechart_source = ColumnDataSource(data=dict())
@@ -3480,10 +3409,12 @@ def handle_toggle(_toggle):
34803409
self.toggle.on_click(handle_toggle)
34813410
self.barchart = figure()
34823411
self.piechart = figure()
3412+
self.senddata_piechart = figure()
34833413
self.root = column(
34843414
self.function_selector,
34853415
self.toggle,
34863416
row([self.piechart, self.barchart]),
3417+
row([self.senddata_piechart]),
34873418
sizing_mode="scale_width",
34883419
)
34893420

@@ -3493,35 +3424,53 @@ def update(self):
34933424
items = (
34943425
(k, v)
34953426
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
35253474

35263475
data = self.data.copy()
35273476

@@ -3623,6 +3572,52 @@ def update(self):
36233572
self.substantial_change = True
36243573
self.source.data = dict(data)
36253574

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+
36263621
# Show total number of functions to choose from
36273622
self.function_selector.title = (
36283623
f"Filter by function ({len(self.function_selector.options)}):"
@@ -3631,39 +3626,16 @@ def update(self):
36313626
# replacing the child causes small blips if done every iteration vs updating renderers
36323627
# but it's needed when new functions and/or operations show up to rerender plot
36333628
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
36363633
self.substantial_change = False
36373634
else:
36383635
self.barchart.renderers = renderers
36393636
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]
36673639

36683640

36693641
class Contention(DashboardComponent):

0 commit comments

Comments
 (0)