Skip to content

Performance ​

Smudge is measured with a fixed set of scenes, on a desktop and in a virtual machine without a GPU, with damage tracking on and off. These are the v0.1 numbers.

The scenes ​

SceneWhat changes every frame
S1600 rounded, bordered boxes in a grid, every box changes color. The raster-heavy case.
S2The same 600 boxes, static, plus one small box that changes color. The best case for damage.
S3The root background, which covers everything. The worst case for damage.
S4300 labels whose text changes. Layout-heavy.
S5A scroll through a thousand mixed rows, one wheel step per frame.
S6A scroll through a virtual list of a hundred thousand rows.
S9One keystroke per frame into a focused text field.

Each scene runs in two modes. Damage is the default: repaint only what changed. Full repaints the whole surface every frame, which is what a renderer without damage tracking does. Each run is 30 warm-up frames and 300 measured frames, repeated three times, and the tables give the median frame time.

On a desktop, CPU renderer ​

A Ryzen 7 7700 on Linux, one thread doing the work. Headless frames are 1280 by 800 (S2: 1920 by 1080) and include everything up to finished pixels. Window frames add the copy to the window buffer and were drawn in a tiled window of 1270 by 1388.

SceneDamage, headlessFull, headlessDamage, windowFull, window
S13.80 ms3.75 ms4.23 ms4.61 ms
S224 µs3.73 ms49 µs4.46 ms
S3101 µs101 µs1.16 ms1.10 ms
S43.50 ms3.44 ms4.32 ms4.55 ms
S5310 µs283 µs509 µs1.37 ms
S6125 µs155 µs294 µs1.24 ms
S937 µs87 µs75 µs1.06 ms

Where little changes, damage tracking turns milliseconds into microseconds: S2 is 150 times cheaper than a full repaint headless and 90 times cheaper in a window. Where everything changes (S1, S3), damage costs the same as a full repaint, so tracking it is free.

On a desktop, GPU renderer ​

The same machine with the gpu feature. Headless frames drew on a GTX 1060, window frames on the processor's integrated GPU. The GPU renderer draws the whole frame either way.

SceneHeadlessWindowCPU renderer, window, damage
S11.55 ms1.24 ms4.23 ms
S21.56 ms1.09 ms49 µs
S3582 µs466 µs1.16 ms
S44.41 ms4.10 ms4.32 ms
S52.35 ms1.91 ms509 µs
S6686 µs518 µs294 µs
S9593 µs467 µs75 µs

On window frames, the GPU wins when most of the window changes (S1, S3) and loses when little does, because it redraws everything. RendererChoice::Auto still picks the GPU on a real adapter: at high scale factors, where every frame of a full-window change is millions of pixels, it keeps those frames fast, and a small update stays at about a millisecond or less on either renderer.

In a virtual machine without a GPU ​

A virtual machine with 4 virtual CPUs and no GPU passthrough, running a compositor that renders in software. This is where a CPU renderer matters. The GPU renderer here runs on a software rasterizer, which is what an application gets when it asks for a GPU on such a machine.

SceneCPU renderer, window, damageSoftware GPU, window
S15.01 ms12.5 ms
S275 µs15.8 ms
S3801 µs7.74 ms
S44.89 ms24.1 ms
S5808 µs16.1 ms
S6448 µs7.25 ms
S9105 µs5.96 ms

The CPU renderer is faster in every scene, between 2.5 and over 200 times, which is why RendererChoice::Auto never picks a software adapter.

How to reproduce ​

The benchmark tool is the smudge-bench crate in the repository. One run:

sh
cargo run --release -p smudge-bench -- \
    --scene s2 --mode damage --backend headless \
    --warmup 30 --frames 300 --repeats 3 --out s2.jsonl

Each report holds every frame's timings by phase (flush, layout, paint, display list, damage, raster, present), the process and machine CPU load during the run, and the adapter for GPU runs. Add --renderer gpu with the bench's gpu feature to measure the GPU renderer.

Released under the MIT or Apache 2.0 license, at your option.