π Version 6.3.0
A performance release focused on updates. updateSeries is now genuinely incremental: a data-only update repaints the series and refreshes the axis chrome in place instead of tearing the chart down and rebuilding it, so streaming and frequently-updating charts are several times faster. Large-series initial render is also markedly quicker from shared parsing work. There are no API changes and no new options: the rendered output is verified identical to 6.2.0, so existing configs render exactly as before, just faster.
The numbers below are 5-trial medians (initial render) and per-cycle medians (updates) from the reproducible harness behind the "100,000 Points" rendering benchmark, measured back to back on one machine (headless Chromium, animations off, identical seeded data).
β‘ Performance
updateSeries is now incremental
Previously every updateSeries call re-ran the full render pipeline: parse, re-layout, and a complete DOM rebuild. It now takes a fast path that repaints only the series layer and, when the axis scale changes, redraws the grid and axes in place within the frozen layout. The canvas renderer repaints its existing bitmap instead of recreating the backing store. Anything the fast path cannot reproduce exactly (a change in series count or data length, collapsed or combo series, an active zoom) falls back to the full render automatically.
updateSeries cycle |
6.2.0 | 6.3.0 |
|---|---|---|
| 50,000 points (canvas) | 62.5 ms (16/sec) | 4.1 ms (242/sec) |
| 50,000 points (SVG) | 66.7 ms (15/sec) | 12.5 ms (80/sec) |
| 10,000 points (canvas) | 11.1 ms (90/sec) | 1.3 ms (765/sec) |
| 10,000 points (SVG) | 11.1 ms (90/sec) | 2.8 ms (362/sec) |
Line and area initial render: roughly 2 to 3 times faster at high point counts
The parse pipeline no longer forces a deep clone of the series and several whole-series aggregate passes that most charts never read, and plain numeric [[x, y], ...] data now parses in a single typed pass that also computes the axis extrema inline (removing separate min/max scans). The path geometry itself was already fast; this release removes the surrounding per-render overhead.
| Line, single series | 6.2.0 | 6.3.0 |
|---|---|---|
| 100,000 points (canvas) | 90 ms | 29 ms |
| 100,000 points (SVG) | 106 ms | 40 ms |
| 50,000 points (canvas) | 57 ms | 25 ms |
| 50,000 points (SVG) | 65 ms | 30 ms |
| 10,000 points (canvas) | 27 ms | 19 ms |
Scatter charts inherit the parsing wins
Scatter and bubble charts share the parse pipeline, so they pick up a portion of the same improvement without any scatter-specific work.
| Scatter | 6.2.0 | 6.3.0 |
|---|---|---|
| 50,000 points (canvas) | 155 ms | 120 ms |
| 50,000 points (SVG) | 571 ms | 528 ms |
| 20,000 points (canvas) | 73 ms | 60 ms |
π Fixes
- Data-only updates no longer leak DOM nodes. Because the incremental path preserves the chart DOM across updates instead of clearing it, two transient elements that the full render had always discarded were accumulating: a stray crosshair backing rect and the y-axis crosshair tooltip container, added once per update. On a continuously updating chart this grew without bound. Both are now reused across updates, so the node count stays flat over any number of updates. This matters most for real-time and streaming dashboards.
- Brushing or zooming after a linked-chart update works again. A chart updated in place by a crossfilter or linked view kept a stale reference to its grid geometry, so a subsequent range brush or drag-zoom drew an empty selection. It now reads the live geometry on each interaction.
π§ Behavior changes (structural, not visual)
- The DOM subtree is preserved across
updateSeries. Data-only updates now keep and update the existing series, axis, and grid elements rather than replacing them. Rendered output (SVG path data and canvas pixels) is verified identical; code that re-queries chart elements after an update by class or attribute continues to work, but code that cached a specific element node reference from before an update and relied on it being replaced should re-query instead.
Compatibility
- No new options, no changed defaults, no TypeScript changes.
- SVG path output and canvas pixels are verified identical to 6.2.0 across the snapshot suite; the fast path is held to the full render's output by a pixel-level oracle and by format-equivalence tests on the new parse path.
- Verified by the full unit, interaction, and end-to-end snapshot suites, plus new regression tests covering the incremental update path, the parse fast lane, and the per-update node-count guard.