Closes #69.
Measures the CPU, memory and GPU time a web terminal itself adds in Chrome, per Chrome process, as a delta over the same harness page with no terminal mounted, across 10 workloads and 11 renderers.
What's added
demo/efficiency.html+demo/efficiency-bench.js: one page for every renderer (Wraith native / pool / Fleet / xterm-compatible, xterm.js 6 WebGL and DOM, restty 0.3.0, zem 0.1.2, ghostty-web 0.4.0, wterm DOM and Ghostty cores 0.5.6) and thenonebaseline, with all workload data generated before the measured window.scripts/efficiency-benchmark.mjs(npm run benchmark:efficiency): fresh headed Chrome per run at DPR 2, 3 interleaved rounds, resumable. CPU per process type from CDPSystemInfo.getProcessInfo;phys_footprintand graphics memory per pid fromfootprint; RSS; main-thread JS heap; Apple GPU time per pid fromAGXDeviceUserClientaccumulatedGPUTime; load and power per run. It waits for the Fleet benchmark and AC power, and repeats a run that overlaps either.scripts/efficiency-report.mjs(npm run report:efficiency): writesdocs/benchmarks/resource-efficiency/REPORT.md(findings computed from the data, per-workload tables, summary, ranking, method and caveats) andsummary.csvfromresults.json.- devDependencies for the competitor renderers (setups from the stress-ramp branch).
The report lives in docs/benchmarks/resource-efficiency/ because docs/benchmarks/efficiency/ already holds the earlier efficiency-pass report.
Results (medians of 3 rounds, delta over the no-terminal page)
Apple M5 Max, macOS 27.2, Chrome 156.0.8078.48, Wraith SDK/engine of b06aaa3.
| Renderer | Idle CPU-ms/s | Logs 200 l/s CPU-ms/s | CPU-ms/MiB log | CPU-ms/MiB Unicode | CPU-s / 1k full redraws | 64 terminals CPU-ms/s | Idle RAM Δ MiB (page + GPU proc) | RAM / 10k lines MiB |
|---|---|---|---|---|---|---|---|---|
| Wraith native | 20 | 104 | 11 | 19 | 3.4 | 573 (pool) / 294 (Fleet) | 406 (25 + 381) | 15 |
| Wraith xterm-compatible | 45 | 199 | 33 | 60 | 3.3 | 865 | 416 (17 + 397) | 24 |
| xterm.js 6 WebGL | 13 | 158 | 42 | 43 | 13.9 | not comparable (48/64 contexts lost) | 474 (12 + 461) | 25 |
| xterm.js 6 DOM | 41 | 210 | 37 | 58 | 10.1 | 478 | 212 (6 + 204) | 25 |
| restty | 46 | 236 | 29 | 25 | 4.5 | 611 | 427 (26 + 402) | 23 (retention not readable) |
| zem | 43 | 266 | 64 | 60 | 3.9 | 743 | 382 (19 + 363) | 30 (retention not readable) |
| ghostty-web | 222 | 307 | 104 | 83 | 17.2 | 1,576 | 289 (11 + 275) | 14 |
| wterm DOM | 46 | 245 | 26 | 822 | 65.6 | 1,189 | 236 (9 + 224) | n/a (keeps 1,050 lines) |
| wterm + Ghostty | 46 | 247 | 57 | 402 | 67.7 | 1,254 | 237 (11 + 224) | 22 |
CPU ranking (geometric mean of 8 CPU metrics vs best): Wraith 1.30, xterm.js WebGL 1.76, restty 2.05, xterm.js DOM 2.22, Wraith xterm-compatible 2.23, zem 2.64, wterm 4.53, wterm + Ghostty 4.67, ghostty-web 5.67. RAM (all processes) is Wraith's weak side: 7 of 9, mostly Chrome GPU-process footprint; 4 of 9 by page-process memory.
Caveats
Shared machine (load median 3.9, max 46.2; 236/309 runs under load 6); CPU time per unit of work is the primary metric for that reason. The GPU-process footprint is largely Chrome's cost of drawing at DPR 2. GPU time is per process and excludes the window server. restty and zem expose no text API, so only screenshots (local) confirm they drew. Full method and caveats are in the report.
Validation
- 309/309 runs completed; end marker read back where the renderer exposes text; scrollback retention read back; 64-terminal screenshots inspected.
- Runs that overlapped the Fleet GPU benchmark or ended near a switch to battery were discarded and re-run.
npm run typecheck,prettier --checkon the new files.
🤖 Generated with Claude Code