Skip to content

Commit 3a8cead

Browse files
committed
[docs] Add a performance docs page for charts
1 parent 7242a9a commit 3a8cead

4 files changed

Lines changed: 126 additions & 0 deletions

File tree

docs/data/charts/bars/bars.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,11 @@ When you set `skipAnimation` to `true`, the chart renders without animations.
275275

276276
## Performance
277277

278+
### SVG batch rendering
279+
278280
By default, each bar is drawn as an SVG `rect` element.
279281
With many bars, this can slow down rendering.
282+
280283
To render bars more efficiently, you can set the `renderer` prop to `"svg-batch"`.
281284
This has some trade-offs:
282285

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
title: Charts - Performance
3+
productId: x-charts
4+
---
5+
6+
# Charts - Performance
7+
8+
<p class="description">Learn how to keep charts fast and responsive when rendering large datasets.</p>
9+
10+
The performance of a chart can be decomposed in multiple factors: The time for computations, the React re-renders time, the time for the DOM update.
11+
This page describes the most impactful options you can use to keep rendering smooth.
12+
13+
## Provide stable references
14+
15+
Charts derive a lot of state from their axes/series and recompute it whenever the relevant prop changes by reference.
16+
Passing a new array or object on every render forces this work to run again and triggers extra re-renders, even when the data itself hasn't changed.
17+
18+
The following props benefit from a stable reference:
19+
20+
- `series`
21+
- `xAxis`, `yAxis`, and `zAxis`
22+
- `dataset`
23+
- `margin`
24+
- `colors`
25+
26+
When the value never changes, define it outside the component so the same reference is reused across renders:
27+
28+
```jsx
29+
// Defined once, outside the component.
30+
const xAxis = [{ scaleType: 'band', data: ['A', 'B', 'C'] }];
31+
32+
function MyChart() {
33+
return <BarChart xAxis={xAxis} series={series} height={300} />;
34+
}
35+
```
36+
37+
When the value depends on props or state, wrap it in `useMemo` so it is only recomputed when its inputs change:
38+
39+
```jsx
40+
function MyChart({ data }) {
41+
const series = React.useMemo(() => [{ data }], [data]);
42+
43+
return <LineChart series={series} height={300} />;
44+
}
45+
```
46+
47+
:::warning
48+
The docs uses lot of inlined objects and arrays directly in the JSX (for example `margin={{ top: 10 }}` or `series={[{ data }]}`).
49+
50+
We do that for clarity in the docs sections.
51+
But each render creates a new reference, which defeats the internal memoization.
52+
:::
53+
54+
## Skip animations
55+
56+
Animations are convenient for small charts, but they require updating the DOM on every frame.
57+
With many data points, this work multiplies.
58+
59+
Set the `skipAnimation` prop to render the final state directly, without transitions:
60+
61+
```jsx
62+
<LineChart series={series} skipAnimation />
63+
```
64+
65+
:::info
66+
When `skipAnimation` is unset, charts already respect the user's [`prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) setting and skip animations for users who opted out of motion.
67+
:::
68+
69+
## Remove marks from line charts
70+
71+
If you set `showMark` to `true` for line series, a mark element is render for every data point.
72+
For a series with thousands of points, this adds thousands of DOM nodes that can impact performances.
73+
74+
Either disable marks, or reduce their number
75+
76+
```jsx
77+
// One mark per 100 values.
78+
showMark: ({ index }) => index % 100 === 0;
79+
// Only a mark at the end of the series.
80+
showMark: 'end';
81+
// Only a mark at the beginning of the series.
82+
showMark: 'start';
83+
```
84+
85+
See [Line charts—Optimization](/x/react-charts/lines/#optimization) for more details.
86+
87+
## Use a more efficient renderer
88+
89+
By default, each item is drawn as its own SVG element—a `<rect>` per bar, a `<circle>` per scatter point.
90+
This is flexible but doesn't scale well: the number of DOM nodes grows with the number of data points.
91+
92+
Bar and scatter charts accept a `renderer` prop to switch to a more efficient drawing strategy:
93+
94+
- `'svg-single'` (default): renders every item in its own SVG element.
95+
- `'svg-batch'`: batches all items into a few `<path>` elements, which dramatically reduces the DOM node count for large datasets.
96+
97+
```jsx
98+
<BarChart series={series} renderer="svg-batch" />
99+
```
100+
101+
The batch renderer comes with some trade-offs, such as not being able to style individual items with CSS.
102+
See the dedicated sections for the full list of limitations and live demos:
103+
104+
- [Bar charts—Performance](/x/react-charts/bars/#svg-batch-rendering)
105+
- [Scatter charts—Performance](/x/react-charts/scatter/#svg-batch-rendering)
106+
107+
### WebGL renderer [<span class="plan-premium"></span>](/x/introduction/licensing/#premium-plan 'Premium plan')
108+
109+
For the largest datasets, `BarChartPremium`, `ScatterChartPremium`, and `HeatmapPremium` support a `'webgl'` renderer that draws items into a single `<canvas>` element, using GPU.
110+
This trades item-level interactivity for the ability to render hundreds of thousands of points.
111+
112+
```jsx
113+
<ScatterChartPremium series={series} renderer="webgl" />
114+
```
115+
116+
See [Bar charts—WebGL renderer](/x/react-charts/bars/#webgl-renderer), [Scatter charts—WebGL renderer](/x/react-charts/scatter/#webgl-renderer), and [Heatmap—WebGL renderer](/x/react-charts/heatmap/#webgl-renderer) for details and demos.

docs/data/pages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ const pages: MuiPage[] = [
756756
{ pathname: '/x/react-charts/label' },
757757
{ pathname: '/x/react-charts/legend' },
758758
{ pathname: '/x/react-charts/localization' },
759+
{ pathname: '/x/react-charts/performance' },
759760
{ pathname: '/x/react-charts/stacking' },
760761
{ pathname: '/x/react-charts/styling' },
761762
{
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { MarkdownDocs } from '@mui/internal-core-docs/MarkdownDocs';
2+
import * as pageProps from 'docs/data/charts/performance/performance.md?muiMarkdown';
3+
4+
export default function Page() {
5+
return <MarkdownDocs {...pageProps} />;
6+
}

0 commit comments

Comments
 (0)