SlintPlot

SlintPlot benchmarks

Frame times of SlintPlot's charts from 100 to 1,000,000 points, with Slint's software renderer and with Skia on the GPU. For the short version, see how much a chart can show.

How it's measured

The numbers come from the stress test app, slintplot-stress. --bench renders each configuration with Slint's software renderer, without a window; --bench-gpu renders the same configurations with Skia, on the GPU.

At 60 frames per second, a frame has 16.7 ms. Frames below that can be animated and streamed smoothly; slower ones are fine for charts that change now and then.

Software renderer

Lines, bars and points

Frame time per number of points in each dataset. Decimation draws a line with more points than pixels as one span per pixel column.

PointsLineLine, decimatedTime seriesTime series, decimatedBarsScatter
1004.4 ms4.6 ms3.2 ms3.1 ms3.2 ms2.7 ms
1,0006.8 ms6.8 ms7.6 ms5.8 ms5.0 ms4.3 ms
10,00059 ms5.5 ms67 ms5.6 ms26 ms23 ms
100,0001.2 s24 ms1.3 s29 ms231 msnot run
1,000,00016.9 s238 ms15.3 s281 msnot runnot run

With point markers and smooth lines, a line takes 6.3 ms at 100 points, 14 ms at 1,000 and 129 ms at 10,000: each marker is an element. Bars and markers are one element each, so the benchmark doesn't run them past 100,000 bars or 10,000 markers.

Charts with one shape per item

Waterfall, dumbbell, funnel and sunburst charts draw every step, row, stage or item, with no decimation:

ItemsWaterfallDumbbellFunnelSunburst
1001.7 ms1.5 ms1.0 ms3.4 ms
1,0009.0 ms9.1 ms3.8 ms21 ms
10,00083 ms93 ms33 ms266 ms

A gauge frame takes 2.3 ms.

Segmented rings and tile grids

Frame time per number of cells in the matrix, on a scale and by category. These charts draw their cells as one path per color, not a shape per cell:

CellsSegmented rings, on a scaleSegmented rings, by categoryTile grid, on a scaleTile grid, by category
1002.4 ms2.4 ms2.9 ms2.9 ms
1,0006.2 ms5.1 ms7.7 ms7.4 ms
10,00045 ms30 ms54 ms53 ms
100,000over the limitover the limit238 ms235 ms

A segmented ring chart shows at most 50 rings of 720 segments (36,000 cells), and a tile grid at most 200 rows of 1,000 tiles (200,000 cells); the rest of a larger matrix isn't drawn.

Skia (GPU)

Frame time per number of points in each dataset, with new data, and redrawing the same data (as when hovering), with Slint's Skia renderer on the M4's GPU:

PointsLineLine, decimatedTime seriesTime series, decimatedBarsScatter
1002.4 ms2.2 ms2.3 ms1.8 ms3.0 ms2.5 ms
1,0005.8 ms5.4 ms6.7 ms4.8 ms8.2 ms11 ms
10,00034 ms5.8 ms44 ms5.8 ms62 ms102 ms
100,000352 ms25 ms430 ms29 ms641 msnot run
1,000,0003.3 s241 ms3.4 s288 msnot runnot run
Redraw, 1,000,0002.2 s3.1 ms2.2 s3.0 ms

With point markers and smooth lines, a line takes 4.2 ms at 100 points, 18 ms at 1,000 and 177 ms at 10,000.

ItemsWaterfallDumbbellFunnelSunburst
1002.5 ms3.6 ms1.8 ms4.6 ms
1,00011 ms24 ms6.5 ms24 ms
10,00097 ms224 ms53 ms364 ms
CellsSegmented rings, on a scaleSegmented rings, by categoryTile grid, on a scaleTile grid, by category
1001.8 ms1.8 ms2.0 ms1.9 ms
1,0006.6 ms5.0 ms5.6 ms5.6 ms
10,00044 ms29 ms37 ms36 ms
100,000over the limitover the limit112 ms110 ms
  • Long paths are faster with Skia. A line or time series without decimation takes 3.3 s at a million points instead of 17 s, and 34 ms at 10,000 instead of 59 ms.
  • Many separate shapes are slower. Each bar, marker or item is a separate draw on the GPU: 10,000 scatter markers take 102 ms instead of 23 ms, 10,000 bars 62 ms instead of 26 ms.
  • Decimated lines cost the same in both renderers, since reading and decimating the data takes most of the time; redrawing them without new data takes 3 ms with Skia.
  • Redraws are cheaper. Drawing the same data again takes a third to three quarters of a frame with new data, because Skia keeps the shapes it has built.
  • One machine. These are from Apple's Metal on an M4. Other GPUs, and Skia with OpenGL or Vulkan on Linux and Windows, will differ.

Streaming limits

How much data can a chart show while it streams, and still update at 60 or 30 frames per second? slintplot-stress --bench-stream measures it: each update appends one value to each of three datasets, drops the oldest, and renders a full frame. It grows the window (the values kept per dataset) in 1-2-5 steps from 1,000 to 10,000,000, and times each size: the 95th percentile of up to 100 updates, the median of three runs. Same machine and renderer as above: Apple M4, macOS 27, Slint's software renderer on one core, 1280×800.

Two views: everything, the whole window on screen, and the latest 1,000, zoomed in to the newest values, as a live view usually is, with the rest kept for scrolling back.

ChartEverything shownLatest 1,000 shown
60 fps30 fps60 fps30 fps
Line, decimated50,000100,00010,000,000+10,000,000+
Time series, decimated20,000100,00010,000,000+10,000,000+
Line, not decimated2,0005,00010,000,000+10,000,000+
Time series, not decimated2,0005,00010,000,000+10,000,000+
Bars2,0005,00010,000,000+10,000,000+
Scatter5,00010,00020,00050,000

The largest window, in values per dataset, that updates within 16.7 ms (60 fps) or 33.3 ms (30 fps). 10,000,000+ means the largest size tried still made it.

What the numbers mean

What isn't measured

Run it yourself

To measure your own machine, run the benchmark, or open the app to try the charts with live numbers:

cargo install slintplot-stress
slintplot-stress --bench          # the tables above, for your machine
slintplot-stress --bench-stream   # only the streaming limits, with your machine's specs
slintplot-stress                  # the interactive stress test

To repeat the numbers above from the source, at the version they were measured with:

git clone https://github.com/trondegil/slintplot
cd slintplot
git checkout v0.5.0
cargo run --release -p slintplot-stress -- --bench

A full run takes about 8 minutes and prints the machine it ran on. Close other apps first and keep the computer on mains power; we run it three times and take the median of each number.

The interactive app shows live frame times with any renderer; see choosing a renderer.

The Skia numbers, with the app built with its skia feature (or installed with cargo install slintplot-stress --features skia, then SLINT_BACKEND=winit-skia SLINT_SCALE_FACTOR=1 slintplot-stress --bench-gpu). A window opens and stays empty while it runs: the frames are drawn off-screen. Add a folder after --bench-gpu to save every frame as a PNG.

SLINT_BACKEND=winit-skia SLINT_SCALE_FACTOR=1 \
  cargo run --release -p slintplot-stress --features skia -- --bench-gpu

SlintPlot · slintplot.dev · license@slintplot.dev