From d0d9d490124ef437649baca218391a11f1813f5c Mon Sep 17 00:00:00 2001 From: Jan Eitzinger Date: Thu, 27 Aug 2026 12:18:14 +0200 Subject: [PATCH] feat(frontend): add display smoothing filter for metric plots cc-lib's resamplers cannot smooth: validateFrequency bails out when the new frequency is not coarser than the old one, and every algorithm produces an output strictly shorter than its input. They consolidate for transport, which is a separate job from filtering for display, and they only act at all once a series exceeds the target point count - shorter jobs arrive raw. Add a centered, NaN-aware moving average in the plot layer, applied after whatever downsampling the backend performed. It preserves length and index alignment, so the X array, the visible point count and the zoom-resampling hook are unaffected. NaN and null samples are skipped, an all-NaN window stays NaN so gaps keep rendering, and the window shrinks at the series edges rather than introducing new gaps there. The window is a user setting in data points, defaulting to 3, and is orthogonal to the resample algorithm - it stacks on top of average consolidation rather than replacing it. All series of a stats plot are smoothed together, since smoothing only some would break the min <= mid <= max invariant the plot bands rely on. Smoothing is display only: reported statistics and job footprints come from JobMetric.Statistics and are untouched. The uPlot cursor readout does show the smoothed value. Co-Authored-By: Claude Opus 5 (1M context) --- web/configSchema.go | 5 ++ .../src/config/user/PlotRenderOptions.svelte | 51 ++++++++++++++++++ .../src/generic/plots/MetricPlot.svelte | 20 +++++-- web/frontend/src/generic/plots/smoothing.js | 53 +++++++++++++++++++ web/web.go | 3 ++ 5 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 web/frontend/src/generic/plots/smoothing.js diff --git a/web/configSchema.go b/web/configSchema.go index 66e57195..d2c839e9 100644 --- a/web/configSchema.go +++ b/web/configSchema.go @@ -177,6 +177,11 @@ const configSchema = `{ "description": "Initial thickness of rendered plotlines. Applies to metric plot, job compare plot and roofline.", "type": "integer" }, + "smoothing-window": { + "description": "Initial display smoothing window in data points, applied after downsampling. 0 disables smoothing. Display-only: reported statistics and footprints are unaffected.", + "type": "integer", + "minimum": 0 + }, "color-scheme": { "description": "Initial colorScheme to be used for metric plots.", "type": "array", diff --git a/web/frontend/src/config/user/PlotRenderOptions.svelte b/web/frontend/src/config/user/PlotRenderOptions.svelte index b8b96ae9..22ca761c 100644 --- a/web/frontend/src/config/user/PlotRenderOptions.svelte +++ b/web/frontend/src/config/user/PlotRenderOptions.svelte @@ -311,4 +311,55 @@ + + + + +
updateSetting(e, { + selector: "#smoothing-window-form", + target: "sw", + })} + > + +
Smoothing Window
+ {#if displayMessage && message.target == "sw"} +
+ + Update: {message.msg} + +
+ {/if} +
+ +
+ + +
+ Width of the moving average applied to plotted lines, in data + points. 0 disables it, the default is 3. It is applied after + downsampling and is display-only: the reported min/avg/max + statistics and the job footprint are unaffected. Combined with the + Average algorithm it is a second, milder smoothing pass on top of + the interval means. +
+
+ +
+
+ \ No newline at end of file diff --git a/web/frontend/src/generic/plots/MetricPlot.svelte b/web/frontend/src/generic/plots/MetricPlot.svelte index 63e31950..20ae83af 100644 --- a/web/frontend/src/generic/plots/MetricPlot.svelte +++ b/web/frontend/src/generic/plots/MetricPlot.svelte @@ -17,6 +17,7 @@ - `numhwthreads Number?`: Number of job HWThreads [Default: 0] - `numaccs Number?`: Number of job Accelerators [Default: 0] - `zoomState Object?`: The last zoom state to preserve on user zoom [Default: null] + - `smoothingWindow Number?`: Display smoothing window in data points; overrides the user setting. 0 or 1 disables [Default: null] - `thersholdState Object?`: The last threshold state to preserve on user zoom [Default: null] - `extendedLegendData Object?`: Additional information to be rendered in an extended legend [Default: null] - `onZoom Func`: Callback function to handle zoom-in event @@ -25,6 +26,7 @@