perf(charts): draw the always-on 1Hz charts without Recharts (#1970)
* perf(charts): draw the always-on 1Hz charts without Recharts
The per-core CPU grid and the dashboard sparklines re-rendered a full
Recharts component tree every second: one `AreaChart` per logical core plus
one per metric card, each rebuilding its data array, recomputing scales, and
re-rendering grid, axes and area. Recharts is the right tool for the large
interactive charts, but this is its cost paid 1Hz for surfaces that only ever
draw one line.
Add a `Sparkline` that renders the same series as two `<path>`s, so a tick
mutates two `d` attributes instead of rebuilding a chart. It resolves the
line graph type through the same d3-shape curve factories Recharts uses, so
the shape is unchanged; `d3-shape` was already in the tree via Recharts and
is now a direct dependency, which adds no bundle weight.
The paths are built in a fixed 100x100 box and stretched by
`preserveAspectRatio="none"`. Every curve involved is affine-invariant, so
the drawn shape matches one computed at the container's pixel size, and the
component needs no element measurement.
Measured on the CPU detail screen (8 logical cores, e2e fixture at 1Hz, dev
build, mean main-thread time per tick over 60 ticks): 208ms -> 43ms.
Refs #1581
* perf(charts): restore the sparkline scale gutter and tick labels
The scale-enabled state regressed: the replacement drew unlabelled grid
lines and put 100/0 directly over the plotting area, so intermediate values
were unreadable and the series ran beneath the labels. The Recharts axis it
replaced reserved space beside the plot.
Give the scale its own gutter, label every grid line from one tick source so
labels and lines cannot drift apart, and inset the plot vertically so the
edge ticks stay inside the chart.
Recharts thinned its `tickCount={12}` request to whatever fit; this component
does not measure itself, so it asks for a density that stays legible at the
~140px height the per-core charts actually get.
Verified with Graph Style -> Scale enabled at 1440x900 and 768x1024.
* fix(charts): key sparkline ticks by position rather than label
`sparklineTicks` rounds its labels to integers, so a range narrower than the
tick count repeats values — `key={tick.value}` would then produce duplicate
sibling keys. `y` is distinct per tick by construction, so it is the identity
to key on.
Not reachable from the current call sites, which all plot the default 0-100
range, but `range` is part of the component's API and the rounding behaviour
is now stated where the ticks are built. S
shm committed
92360b3e1a5185870c34c7226fe71ce8179ce316
Parent: 0ac016d
Committed by GitHub <noreply@github.com>
on 8/22/2026, 6:13:40 AM