Microbenchmarks
One state change, and one scroll step of 10,000 rows, timed headless in process CPU per operation, from the change to a frame ready to present.
Each figure is the median over batches after a warm-up, with the 10th to 90th percentile beside it. Each framework’s frame is compared with the frames that do the same work: GPUI Fast’s headless frame stops before the GPU encode, so it sits beside zgx’s frame without one; Rune’s and MyGo’s include it (MyGo’s also rasterizes on the CPU), beside zgx’s with it. Lower is better.
| Frame | Framework | Median (p10–p90) |
|---|---|---|
| Without the GPU encode | zgx | 1.9(p10 1.7 to p90 2.2) |
| zgx (Luau) | 2.4(p10 2.2 to p90 2.5) | |
| GPUI Fast | 675(p10 660 to p90 685) | |
| With the GPU encode | zgx | 81.6(p10 75.6 to p90 123.0) |
| zgx (Luau) | 60.7(p10 56.2 to p90 81.3) | |
| Rune | 1,424(p10 1,384 to p90 1,454) | |
| MyGo | 482(p10 461 to p90 495) |
| Frame | Framework | Median (p10–p90) |
|---|---|---|
| Without the GPU encode | zgx | 3.5(p10 3.1 to p90 4.1) |
| zgx (Luau) | 4.2(p10 3.8 to p90 4.9) | |
| GPUI Fast | 26.5(p10 24.5 to p90 30.1) | |
| With the GPU encode | zgx | 91.2(p10 79.3 to p90 100.7) |
| zgx (Luau) | 113(p10 100 to p90 191) | |
| Rune | 210(p10 126 to p90 231) | |
| MyGo | 209(p10 200 to p90 304) |
| Frame | Framework | Median (p10–p90) |
|---|---|---|
| Without the GPU encode | zgx | 6.9(p10 0.8 to p90 11.5) |
| zgx (Luau) | 9.7(p10 0.8 to p90 14.9) | |
| GPUI Fast | 119(p10 99 to p90 137) | |
| With the GPU encode | zgx | 112(p10 87 to p90 137) |
| zgx (Luau) | 109(p10 86 to p90 143) | |
| Rune | 209(p10 174 to p90 278) | |
| MyGo | 431(p10 356 to p90 509) |
- The change alone (“write”) is not compared: GPUI Fast, Rune and MyGo store the value and mark the window to draw, leaving all their work to the frame, where zgx’s bindings update their nodes as the value is set. The frame is the figure that counts, and it includes the write.
- MyGo’s frame rasterizes its scene on the CPU, as its headless tester does, where a window would draw on the GPU; it is shown at a raster scale of 0.05×, which leaves its layout and paint and makes the raster almost free.
- Most of a frame with the GPU encode is what any Metal frame costs: a bare Metal frame (a command buffer, one empty render pass, commit) takes 44–94 µs of process CPU back to back on this Mac, most of it in Metal’s own threads.
How they are defined and run: microbenchmarks. Raw rows: micro.jsonl.