Performance
Fast because it does less.
Aizome only redraws what has changed, and its apps draw on the CPU into memory they share with the compositor, without starting OpenGL or Vulkan. An idle desktop draws about one frame a minute, and every part of the desktop has a budget of 4 ms to turn an event into a frame. This page has the measurements behind all that, taken on 2 November 2026 on a single desktop machine, comparing Aizome with GNOME, KDE Plasma and other programs people often use alongside it, including where Aizome loses. Each section links to its full write-up, with the raw data and how to repeat the test.
- 19 msfor an Aizome app's window to appear, with its content following, where GNOME's and KDE's apps took 66–201 ms as Sekka sets them up (apps)
- +221 MiBof RAM for the whole desktop in a small VM, against +567 for GNOME and +875 for Plasma as Sekka sets them up (desktops)
- 1 framedrawn in a minute by an idle desktop, for the menu bar's clock (idle)
- 0.48×PDFium's time for Shiori's renderer to draw the same 1,179 test pages, and 0.78× on real documents (PDF)
The whole desktop
In a small virtual machine, Aizome boots and logs in faster than GNOME or Plasma, uses much less memory, and gets keystrokes on screen sooner.
We installed the same Sekka system three times, changing only which desktop the installer picked, plus a fourth copy with no desktop at all to show what the base system uses. Each one ran in a virtual machine with 2 CPUs, 4 GiB of RAM and no 3D acceleration, so all three desktops render on the CPU, much like they would in most VMs and cloud desktops. We booted each one three times, taking turns, and timed both the boot and the login. After two minutes at idle, a small probe window measured how long keystrokes took to reach the screen at 75 Hz, with and without two threads keeping the CPU busy. Last, we launched each desktop's own apps, cold and warm.
Memory in use 190 s after login, minus the 370 MiB the system uses with no desktop. Median of three boots at 4 GiB, each desktop as Sekka sets it up.
The numbers
| MiB | Notes | |
|---|---|---|
| Aizome | 221 | 591 MiB in use with the desktop up, 370 with none; +206 MiB in a 2 GiB VM |
| GNOME | 567 | 937 MiB in use; +560 MiB at 2 GiB |
| KDE Plasma | 875 | 1,245 MiB in use, Akonadi's database among it; +842 MiB at 2 GiB |
220 key presses per boot, sent through a virtual keyboard to a probe window and timed until the frame was presented. At 75 Hz, a frame is 13.3 ms.
The numbers
| frames | Notes | |
|---|---|---|
| Aizome | 0.53 | 7.0 ms at the median, 13.5 at the 99th percentile (1.02 frames) |
| GNOME | 0.97 | 13.0 ms, 23.6 at the 99th (1.77 frames); one press took 55 ms |
| KDE Plasma | 1.01 | 13.5 ms, 26.2 at the 99th (1.97 frames); 11.3 ms after each run's first seconds, against Aizome's 7.4 |
From the moment the VM starts until the screen has stopped changing for three seconds.
The numbers
| s | Notes | |
|---|---|---|
| Aizome | 6.4 | to its own login screen, settled; the bare system reaches its console in 5.1 |
| GNOME | 7.6 | to GDM, settled |
| KDE Plasma | 8.6 | to Plasma Login, settled |
A returning user's password login. First-run windows were dismissed once, in a setup boot before the measured ones.
The numbers
| s | Notes | |
|---|---|---|
| Aizome | 1.2 | Enter to the desktop settled |
| GNOME | 2.0 | Enter to the overview settled |
| KDE Plasma | 5.2 | Enter to the desktop settled |
Part of the memory gap is services that come with how each desktop is set up rather than with the desktop itself. In Plasma, NixOS's module turns on Akonadi, KDE's mail and calendar store, with its MariaDB database, and the session also starts Baloo, KDE's file indexer: about 230 MiB together. GNOME starts calendar and search services and an input method that a distribution could leave out. Without those, the desktops still need about 255 MiB (GNOME) and 410 MiB (Plasma) more than Aizome, and the largest part of that is the compositor and shell. GNOME's figure also includes about 79 MiB for Sekka's large 4928 × 3264 wallpaper, which GNOME Shell keeps at full size, in RAM here since the VM has no GPU.
A keystroke reached the screen sooner in Aizome because its compositor draws a window's update as soon as it arrives. Mutter, GNOME's compositor, holds each update until a few milliseconds before the next refresh, so under load almost half of the key presses waited a whole refresh longer. Plasma's median includes the first 6 to 15 seconds of every run, when each key press was a refresh late; after that, under load, it took 11.3 ms against Aizome's 7.4.
| Aizome | GNOME | KDE Plasma | |
|---|---|---|---|
| Terminal, files, settings, editor, PDF and calculator (Plasma has none here), cold, s | 0.11–0.17 | 0.47–0.82 | 0.27–1.27 |
| The same, warm, s | 0.11–0.17 | 0.47–0.79 | 0.27–1.22 |
| Photo viewer, a 6000 × 3375 JPEG, cold and warm, s | 0.32 | 3.19 (photo at 1.4) | 0.58 |
| Those apps' memory, MiB | 15–57 | 143–253 | 34–177 |
| The photo viewer's memory, MiB | 326 | 436 | 166 |
Under load, a window drawing on every frame lost 0.84% of its frames in GNOME and 0.09% in one of Plasma's three runs. Aizome didn't lose any.
Not everything went Aizome's way. In this VM its shell woke about 47 times a second while idle (53 in the headless session measured further down), more than all of GNOME put together, though its CPU time at idle was as low as the others'. Hotaru, Aizome's terminal, took more memory than Konsole, KDE's terminal (57 MiB with its fish shell, against 37 MiB with bash). Shashin, Aizome's image viewer, held twice as much memory as Gwenview, KDE's image viewer, and Aizome's installed system (8.5 GB) is no smaller than GNOME's. With only 2 GiB of RAM, all three still boot and log in fine, and each desktop uses about as much memory as it did with 4 GiB. These numbers come from a VM rendering on the CPU, and on real graphics hardware all three desktops would behave differently. Full results, the VM setup and how it was measured. Where each desktop's memory and time go.
Apps
Aizome's apps put their window on screen in about 19 ms, whatever they're opening. The content follows.
We put Aizome's apps up against the GNOME and KDE apps that do the same jobs, six runs each, all outside their own desktops in the same neutral compositor (sway) on the processor's built-in Radeon graphics. The document apps all opened the same files, a 6000 × 4000 photo, the 756-page PDF specification and a folder of 2,000 files. GNOME's apps took 145–190 ms to show a window, and KDE's took 66–201 ms. Every Aizome app took about 19 ms, because the kit puts the window up first and does the decoding, parsing and reading on other threads. That's the time until the window appears, not until what's in it is ready. Shashin, Aizome's image viewer, is still decoding the photo when its window comes up, and Shiori, Aizome's PDF reader, draws its first page after its window is already showing. For time to a finished window, see the VM results above, where most of Aizome's apps had stopped changing by about 0.11 s and the photo viewer by 0.32 s.
Time from launch until the window appears, ms (lower is better), all on the same scale
| Job | App | Window appears, ms | PSS, MiB | Private, MiB | Wakeups a second at rest |
|---|---|---|---|---|---|
| Calculator | Soroban | 19.0 | 14.3 | 5 | 1 |
| GNOME Calculator | 153 | 61.0 | 25.1 | 0 | |
| KCalc | 65.8 | 56.0 | 14.8 | 0.07 | |
| Clock | Tokei | 19.2 | 16.2 | 5.5 | 5 |
| GNOME Clocks | 145 | 59.3 | 24.2 | 0 | |
| Text editor, 2,514 lines | Sumi | 19.0 | 16.3 | 5.6 | 8.5 |
| GNOME Text Editor | 158 | 67.5 | 26.5 | 0 | |
| KWrite | 107 | 77.9 | 21.3 | 12.0 | |
| Images, a 6000 × 4000 JPEG | Shashin | 19.0 | 117 | 105 | 1 |
| Loupe | 153 | 136 | 28.0 | 0 | |
| Gwenview | 109 | 192 | 133 | 0.07 | |
| PDF, 756 pages | Shiori | 19.2 | 69.5 | 55.0 | 5.6 |
| Papers | 149 | 129 | 87.7 | 0 | |
| Okular | 186 | 150 | 86.1 | 0.56 | |
| Files, a folder of 2,000 | Hako | 19.4 | 36.8 | 22.4 | 8.6 |
| Files (Nautilus) | 171 | 97.5 | 60.9 | 0 | |
| Dolphin | 114 | 70.7 | 24.2 | 0.07 | |
| System monitor | Myaku | 18.9 | 43.7 | 30.1 | 12.9 |
| GNOME System Monitor | 190 | 68.1 | 32.6 | 47.7 | |
| Plasma System Monitor | 201 | 187 | 89.9 | 105 | |
| Disk usage | Kura | 19.2 | 15.5 | 5.3 | 0.98 |
| Disk Usage Analyzer | 159 | 44.3 | 22.7 | 5.7 | |
| Filelight | 164 | 129 | 50.5 | 0 |
The biggest single difference is that GTK 4 and Qt Quick start a GPU API before they draw anything, and Aizome's apps never do. After that come each toolkit's own set-up, such as parsing its theme's CSS, and loading and linking 100–200 shared libraries. Two things about this machine and Sekka's setup make the others slower than they'd be elsewhere. GTK's Vulkan loader loads every Vulkan driver installed here (14 of them, NVIDIA's among them) to ask what it offers, about 50 ms of GTK's time. And Sekka's session has every Qt app, KDE's included, load Qt's GTK 3 platform theme, which costs about 23–29 ms and 4.7 MiB at startup. Neither changes the order, but on another machine or setup the gaps would be smaller. Aizome's apps have room to get faster too, since 12 of the kit's 19 ms go to asking about every installed font at startup.
Memory mostly follows the same pattern. The one exception comes down to where the document is kept rather than the toolkit. Shashin holds the decoded photo (92 MiB of pixels) in its own memory, while Loupe, GNOME's image viewer, shares it with its sandboxed decoders and hands it off to the GPU. Counted by PSS, which splits shared memory between the processes using it, Shashin still uses the least. Where Aizome's apps fall behind is waking up while idle. Tokei, the clock, and Sumi, the text editor, are supposed to, since one shows seconds and the other blinks its cursor. But the wakeups in Hako, the file manager, and in Shiori are housekeeping timers, and six of GNOME's eight apps didn't wake at all. System monitors are always reading the system, and Myaku, Aizome's system monitor, checks every process every second. It used the most CPU doing it, about 23 ms per second compared with 18 for GNOME's monitor and 13 for Plasma's. Full results and how they were measured. Where each toolkit's startup time and memory go.
An idle desktop
Left alone, the whole desktop drew one frame a minute, and that was the clock turning over.
We started a headless Aizome session the way a login would (the compositor, its shell and xwayland-satellite, with a fresh user and default settings), let it settle, and then left it alone for a minute. We did that three times at 1920 × 1080 and three times at 3840 × 2160. According to the compositor's own statistics, in five of the six runs the only thing it drew was the menu bar clock changing. The sixth, at 1080p, drew four frames.
- 1frame drawn in a minute at idle, the median at both 1080p and 4K
- 0.19 msof compositor CPU time per second at idle
- 172 MiBfor the whole session (PSS) at 1920 × 1080, and 193 MiB at 4K
We also looked at the test machine's own desktop while it was in use, driving a 3840 × 2160 display at 240 Hz, with our test tools writing into a terminal window the whole time. In the 4.8 hours after login it drew 146,990 frames, 8.5 a second out of a possible 240, because it only draws when something changes. Each frame took about half a millisecond of CPU time, and 99% took under 1.3 ms.
The shell still isn't completely quiet. It only does about a millisecond of work per second, but it wakes up around 53 times a second here (47 in the VM above, a different setup), mostly because its system-service watchers check for a stop request every 250 ms. That, and the way its memory grew over that long session, are covered under what it costs. The idle runs and how they were measured. The working session.
The compositor's frames
At 3840 × 2160, no frame took the compositor more than 3.2 ms of CPU time, and a still screen didn't need any frames at all.
The compositor comes with its own benchmark. It starts a headless compositor at 3840 × 2160 with 2× scaling, opens some test windows and runs through a set of scenarios, recording how much CPU time each frame takes from gathering the scene to submitting it. We ran it three times on each renderer, GLES on the Radeon, GLES on the RTX 5090, and pixman, the software fallback.
| Scenario | GLES, Radeon | GLES, RTX 5090 | pixman (software) |
|---|---|---|---|
| Idle, two seconds, three windows | no frames | no frames | no frames |
| Moving a window | 0.37 / 0.44 | 0.48 / 2.06 | 0.24 / 0.29 |
| A client drawing every frame | 0.30 / 0.39 | 0.35 / 0.42 | 0.18 / 0.21 |
| Switching Desks, sliding | 0.33 / 1.46 | 0.44 / 0.62 | 0.18 / 0.37 |
| The overview opening and closing | 0.52 / 1.83 | 0.96 / 2.92 | 1.19 / 2.79 |
| A window moving under a frosted menu | 0.54 / 0.66 | 0.75 / 2.33 | 0.38 / 0.45 |
| A full-screen client drawing every frame | 0.25 / 0.34 | 0.13 / 0.39 | 1.33 / 1.46 |
Because only damaged areas get redrawn, moving a window just repaints the strips it leaves and the strips it moves into, and two seconds with nothing changing produced no frames at all. Software compositing actually uses less CPU than GLES until the whole screen changes. A full-screen client that redraws every frame costs pixman 1.3 ms per frame, compared with 0.1–0.3 ms for GLES, which is why Aizome composites on the GPU and keeps pixman as the fallback. Full results and how they were measured.
The 4 ms budget
Everything we timed fits within the 4 ms budget, at the median and at the 95th percentile.
Each app has its own tests that run it headlessly and time a frame all the way from the input event through updating, layout and drawing whatever changed, at 2× scale. That's the CPU time the 4 ms budget is meant to cover. We used release builds and ran each test alone on the machine.
| Interaction | Median | 95th | Slowest |
|---|---|---|---|
| Toggle a switch | 0.03 | 0.04 | 0.06 |
| Type a character in a 2,000-line editor | 0.22 | 0.37 | 1.75 |
| Scroll a 10,000-row list a notch | 0.12 | 0.16 | 0.30 |
| The menu bar's clock ticking | 0.07 | 0.12 | 0.18 |
| A window opening and closing (the shell) | 0.24 | 0.38 | 1.38 |
| A key typed in the palette | 0.40 | 0.81 | 0.83 |
| Typing in Sumi, the text editor | 0.38 | 0.47 | 0.81 |
| Hako, the file manager: ↓ in a column of 10,000 files | 1.20 | 1.32 | 1.37 |
| Hako: scrolling that column | 0.28 | 0.29 | 0.41 |
| Myaku, the system monitor: a new reading of 600 processes | 2.26 | 2.58 | 2.69 |
| Myaku: clicking a row | 0.19 | 0.25 | 4.36 |
The slowest regular case is Myaku, Aizome's system monitor, reading 600 processes, at 2.3 ms (2.6 ms at the 95th percentile). The single slowest frame was one of 30 clicks on Myaku's process list, which took 4.4 ms. The budget is judged at the 95th percentile, and these test timings are upper bounds. Full results and how they were measured.
Terminals
Hotaru, Aizome's terminal, starts faster than any of them. The latest Ghostty, a GPU-rendered terminal, reads output faster, and Hotaru shows keystrokes a frame later than the quickest terminals.
We compared Hotaru, Aizome's terminal emulator, with Ghostty, a fast GPU-rendered terminal, GNOME's two terminals (the older gnome-terminal and the newer Console), KDE's terminal Konsole, and foot, a minimal Wayland terminal. Each one ran in its own headless sway session on the Radeon at 60 Hz, using the same font and size, a 120 × 40 grid and a cursor that doesn't blink. The program running inside each terminal draws numbered marker rows, and a frame only counts once the captured screen shows the complete update. Every trial started on an idle machine, with the terminals taking turns.
Ten fresh launches each, with warm caches, timed until the first captured frame that shows the whole first screen.
The numbers
| ms | Notes | |
|---|---|---|
| Hotaru | 49.6 | range 49.2–66.1 ms |
| Ghostty | 178 | range 177.7–193.9 ms |
| gnome-terminal | 130 | range 129.7–131.0 ms; includes the bus starting its server |
| Konsole | 130 | range 129.6–130.2 ms |
| Console | 130 | range 130.0–146.3 ms |
| foot | 65.7 | range 49.9–66.3 ms |
1,000 presses each. A virtual keyboard presses a key, the program responds by updating one cell, and the clock stops at the captured frame that shows the change.
The numbers
| ms | Notes | |
|---|---|---|
| Hotaru | 26.8 | 1.61 frames at 60 Hz; p99 35.6 ms |
| Ghostty | 30.0 | 1.80 frames; p99 38.0 ms |
| gnome-terminal | 11.6 | 0.70 frames; p99 20.2 ms |
| Konsole | 21.2 | 1.27 frames; p99 29.9 ms |
| Console | 11.6 | 0.70 frames; p99 20.3 ms |
| foot | 11.8 | 0.71 frames; p99 20.1 ms |
Hotaru gets on screen one frame ahead of foot, the minimal terminal, and 80–128 ms ahead of everything else. It loses on typing latency. It shows each keystroke about a frame later than foot or GNOME's two terminals, which are both built on GNOME's VTE terminal widget. Input reaches the program in every terminal within a third of a millisecond, so Hotaru's extra frame is spent between the program's response and the frame on screen. Shorter follow-up runs put it in Hotaru's own path from the program's output to its frame, not in the toolkit: a plain text view built on the same toolkit shows a keystroke at the next frame, as GTK and Qt do.
For throughput, we first ran every terminal with no scrollback, as an earlier comparison of Hotaru's core with libghostty-vt, Ghostty's terminal library, had. Mitchell Hashimoto, Ghostty's author, reran that comparison and pointed out that with no scrollback libghostty-vt loses a lot of its optimizations, which is fair for the alternate screen that full-screen programs use but not for ordinary terminal use. He also found that Hotaru gets slower as its history grows, which a run without history hides. So that run favoured Hotaru twice over, and we measured everything again with history turned on. Ghostty kept its default of 50 MB and Hotaru got the same 50 MB. The other four only let you set history in lines, so each got 1,000,000 lines, the same as Hotaru's row limit and at least as much as Ghostty's 50 MB holds. We included both the Ghostty release Sekka ships (1.4.0) and Ghostty's main branch as of 2 November (0b1729e). These numbers are for each terminal app as a whole, running on screen, so reading the output, parsing it, keeping history and drawing frames all count. They aren't the speed of a VT parser on its own, and can't be compared directly with benchmarks of a terminal library such as libghostty-vt.
64 MiB of ASCII text written into the terminal as fast as it can read it, six rounds each. History is 50 MB for Hotaru and Ghostty and 1,000,000 lines for the others. Energy is measured at the CPU socket, above idle.
The numbers
| MiB/s | Notes | |
|---|---|---|
| Hotaru | 705 | 64 MiB in 91 ms; 2.8 J over idle |
| Ghostty 1.4.0 | 720 | 89 ms; 3.4 J |
| Ghostty main | 794 | 81 ms; 2.9 J; built from 0b1729e |
| gnome-terminal | 230 | 279 ms; 4.3 J |
| Konsole | 3.3 | 19.5 s; 376 J |
| Console | 232 | 276 ms; 4.2 J |
| foot | 146 | 439 ms; 5.4 J |
64 MiB of coloured, bold and underlined log lines.
The numbers
| MiB/s | Notes | |
|---|---|---|
| Hotaru | 301 | 213 ms; 4.8 J over idle |
| Ghostty 1.4.0 | 271 | 236 ms; 5.6 J |
| Ghostty main | 346 | 185 ms; 5.6 J |
| gnome-terminal | 156 | 411 ms; 6.2 J |
| Konsole | 0.7 | 95 s; 2,000 J |
| Console | 163 | 393 ms; 6.2 J |
| foot | 334 | 191 ms; 3.7 J |
64 MiB of CJK, accented letters and emoji.
The numbers
| MiB/s | Notes | |
|---|---|---|
| Hotaru | 165 | 389 ms; 7.4 J over idle |
| Ghostty 1.4.0 | 72.0 | 893 ms; 16.8 J |
| Ghostty main | 251 | 255 ms; 7.0 J |
| gnome-terminal | 88.0 | 728 ms; 11.1 J |
| Konsole | 0.6 | 115 s; 2,112 J |
| Console | 88.0 | 725 ms; 10.0 J |
| foot | 151 | 423 ms; 6.2 J |
64 MiB of cursor movement, erasing and short writes, like what a full-screen program sends.
The numbers
| MiB/s | Notes | |
|---|---|---|
| Hotaru | 126 | 507 ms; 9.6 J over idle |
| Ghostty 1.4.0 | 22.0 | 2,886 ms; 36.7 J |
| Ghostty main | 181 | 353 ms; 8.9 J |
| gnome-terminal | 25.0 | 2,538 ms; 30.7 J |
| Konsole | 90.0 | 708 ms; 10.3 J |
| Console | 24.0 | 2,620 ms; 27.0 J |
| foot | 104 | 618 ms; 8.9 J |
With history, Ghostty's main branch is the fastest on all four kinds of output, and Hotaru manages 66–89% of its speed. Hotaru comes next on Unicode and cursor-heavy output, and third on plain and styled text, behind the two Ghostty builds and behind main and foot respectively. Against the 1.4.0 release, Hotaru is about even on plain text, a little ahead on styled text, and well ahead on Unicode and cursor-heavy output, both of which Ghostty has sped up since that release. History hit the others harder. GNOME's gnome-terminal and Console fell to about 230 MiB/s on plain text and 25 on cursor-heavy output, and foot to 146 on plain text. Konsole, KDE's terminal, keeps its 1,000,000 lines in a fixed-size history. It spent the whole flood busy on the CPU and managed 3.3 MiB/s or less on everything but cursor-heavy output. A million lines is far more history than most people keep (Konsole's default is 1,000), so the table below also has the first run, where no terminal kept any history.
How much memory a full history takes depends on where each terminal keeps it. The VTE-based terminals write theirs to compressed files on disk and held 38 and 69 MiB. Hotaru (94 MiB) and Ghostty (109 and 120 MiB) keep their 50 MB in memory, partly compressed, and Konsole and foot held 942 MiB and 1.5 GiB for their million uncompressed lines. Hotaru's own biggest drop was on plain text, from 1,047 MiB/s with no scrollback to 705 MiB/s with history.
| No scrollback, MiB/s | Hotaru | Ghostty 1.4.0 | gnome-terminal | Konsole | Console | foot |
|---|---|---|---|---|---|---|
| Plain text | 1,047 | 1,018 | 407 | 74 | 418 | 441 |
| Styled text | 348 | 258 | 216 | 86 | 256 | 431 |
| Unicode text | 188 | 215 | 198 | 93 | 193 | 171 |
| Cursor-heavy output | 127 | 22 | 89 | 90 | 95 | 99 |
The graphs in Ghostty's author's post show different gaps, and on plain text the opposite order. Two things account for most of it. He timed the terminal libraries alone, fed bytes with nothing drawn, where these runs time each app on screen. And Hotaru's feed-only mode keeps no history, so in his runs only Ghostty kept any, while here both kept 50 MB. Plain text is the output history slows Hotaru most, so with history on both sides Ghostty main is ahead on it. The builds are close: our Ghostty main is three commits after his, with one more fix for erasing blank rows, and our Hotaru includes a later change to how it reads from the program. Why Ghostty's lead on styled text is smaller here and on Unicode larger, we haven't measured. Drawing is the likeliest difference.
| Ghostty main ÷ Hotaru | His library-level run | These app runs |
|---|---|---|
| Plain text | 0.78× | 1.13× |
| Styled text | 1.35× | 1.15× |
| Unicode text | 1.35× | 1.52× |
| Cursor-heavy output | 1.67× | 1.44× |
| Hyperlinks | 1.17× | not measured |
Sitting idle with a steady cursor, Hotaru wakes once a second. foot, gnome-terminal and Konsole don't wake at all, while Ghostty wakes 28 times a second and keeps the GPU busy for 4.3 ms of every second even though nothing changes. With default settings, Hotaru's cursor blinks forever, whereas GNOME's terminals stop blinking after ten seconds. At startup Hotaru uses 47 MiB of memory, about the same as Console and two thirds of what Konsole uses here, where Konsole runs outside Plasma and its libraries count in full. foot needs just 7. Hotaru's CPU-drawn buffers also cost the compositor more. Scrolling a row at 60 Hz cost sway 0.76 ms of CPU time per update with Hotaru, against 0.36 ms with Ghostty. Full results, the exact settings and how they were measured.
Media
Utsushi, Aizome's media player, is among the lowest-power players we tried, the lowest at 4K, and does the least work around each frame.
Utsushi decodes video on the GPU and hands each frame straight to the compositor, without copying it or drawing it a second time. We played the same clips for a minute at a time in Aizome's Utsushi, in mpv, a popular open-source player, and in VLC, the cross-platform media player, under Aizome's compositor on the Radeon. Each player ran at least three times, and we compared the CPU socket's power draw with idle readings taken in between. Every player ran full screen except mpv with its dmabuf output, whose full-screen option didn't take under Aizome, so it played in a window the size of the picture. A later run put it full screen, and its work was the same.
Power above idle for the CPU socket, median of three or more one-minute runs. Differences under about 0.2 W are within the noise.
The numbers
| W | Notes | |
|---|---|---|
| Utsushi | 0.20 | VA-API decode, frames to the compositor as dmabufs |
| mpv → dmabuf | 0.42 | --hwdec=vaapi --vo=dmabuf-wayland: set up as Utsushi works |
| mpv → gpu-next | 0.51 | --hwdec=vaapi, its GPU renderer |
| VLC 3 | 0.46 | its defaults |
| mpv defaults | 1.36 | decodes in software |
The same measurement for a 3840 × 2160 AV1 clip at 60 frames per second.
The numbers
| W | Notes | |
|---|---|---|
| Utsushi | 0.89 | no frames dropped |
| mpv → dmabuf | 1.06 | no frames dropped |
| mpv → gpu-next | 7.62 | 557 frames dropped |
| VLC 3 | 7.60 | decodes AV1 in software; 315 dropped |
| mpv defaults | 13.32 | software; 145 dropped |
At 1080p, every player that decodes on the GPU sits just a few tenths of a watt above idle, close enough that differences under about 0.2 W are within the noise. The mpv player, set up to work the way Utsushi does, stays within about 0.2 W of it on every clip, and came in lower on a 1080p AV1 clip. At 4K, Utsushi used the least. The big differences come from decoding in software, which mpv does by default (as does the mpv.conf Sekka ships), and from players that redraw every 4K frame on the GPU. Utsushi also does the least work around each frame. At 1080p it uses 0.7–0.9% of a core and wakes about 147 times a second, compared with 1.1–2.0% and 260–450 wakeups for mpv and the VLC player when they decode on the GPU. It uses the least memory too, gets its first frame on screen in 58 ms (the others took 76–172 ms), and wakes just four times a second while paused. Every clip, player and result, and how they were measured.
Shiori's renderer draws the pages of a test corpus in about half the time PDFium, the PDF engine in Chrome, takes, and the pages of real documents in about three quarters of it.
Shiori, Aizome's PDF reader, renders pages with hayro, an open-source PDF renderer written in Rust, using Aizome's own fork of it, tuned for speed. We compared that renderer with the engines most Linux PDF readers use, which are PDFium (the engine in Chrome, here as Nixpkgs builds it), MuPDF (the library behind readers such as Zathura) and Poppler (the library behind GNOME's Papers and Evince and KDE's Okular). The test set was the 1,012 files in the test corpus of pdf.js, Firefox's built-in PDF renderer, many of them bug reports and deliberately broken files. Each engine drew the first five pages of every file at 2× size, with one process per file and a single thread, over three timed runs.
Only pages every engine managed to draw, using each page's median time over three runs, added up.
The numbers
| s | Notes | |
|---|---|---|
| Shiori (hayro fork) | 4.17 | 0.48 of PDFium's time; faster on 1,045 of 1,179 pages |
| PDFium | 8.70 | nixpkgs' build, 8110, AGG; the engine in Chrome |
| hayro upstream | 9.36 | 1.08 of PDFium's time |
| MuPDF | 10.98 | 1.26 of PDFium's time |
| Poppler, Cairo | 11.37 | 1.31; as Papers and Evince draw |
| Poppler, Splash | 21.35 | 2.46; as Okular and pdftoppm draw |
The 969 files every engine handled the same way, five times over, measured at the CPU socket. Median of three rounds. Just starting a process for each file accounts for 67 J of this.
The numbers
| J | Notes | |
|---|---|---|
| Shiori (hayro fork) | 386 | 0.46 of PDFium's energy |
| PDFium | 833 | |
| hayro upstream | 745 | 0.89 |
| MuPDF | 976 | 1.17 |
| Poppler, Cairo | 1,273 | 1.53 |
| Poppler, Splash | 1,998 | 2.40 |
The pdf.js corpus is mostly small and broken files, so we also timed seven real documents, public domain or CC-BY: US government publications such as the Constitution, IRS tax documents and the federal budget, and a scientific paper. Each engine drew the first 20 pages of each (all of the two shorter ones), five times. On those, the fork's lead is smaller. It took 0.37 s for the 113 pages against PDFium's 0.48 and was the faster on 102 of them. It was the fastest of the six engines on four of the seven documents, MuPDF on two, and PDFium on the scientific paper, by under a millisecond.
| Engine | pdf.js corpus, 1,179 pages | Real documents, 113 pages |
|---|---|---|
| PDFium | 2.1× | 1.3× |
| hayro upstream | 2.2× | 1.2× |
| MuPDF | 2.6× | 1.4× |
| Poppler, Cairo | 2.7× | 2.1× |
| Poppler, Splash | 5.1× | 5.9× |
On the 1,179 corpus pages, the fork's median page took 1.10 ms and its 99th percentile 37.7 ms, against 1.45 and 79.6 ms for PDFium. Neither hayro build, Aizome's fork or upstream, crashed or timed out on any file, while PDFium, MuPDF and Poppler each crashed on one or two files and timed out on as many as three. The fork's output is about as close to PDFium's as MuPDF's and Poppler's are. Of the 1,189 pages the fork and PDFium both drew at the same size (a slightly different set from the 1,179 that every engine drew), only 61 differ from PDFium on more than 5% of their pixels, compared with 86 for MuPDF and 124 for Poppler. It's still slower than PDFium on some kinds of page, such as meshes, soft masks over images, nested transparency groups and some shadings, taking 1.3 to 2.4 times as long on those.
There's no official answer key for how a PDF should render, only each engine's own regression tests. hayro's test suite has about 1,560 rendering tests, including 101 files taken from PDFium's bug tracker, and those are checked against hayro's own reference images. Upstream hayro passes all 101. The fork passes 58 within the suite's tolerance of three colour levels, and its speed optimisations leave the other 43 differing only by anti-aliasing. hayro doesn't run PDFium's own pixel tests, so we ran those too. The fork renders 132 of the 182 tests that apply (73%) within 1% of PDFium's expected images, and PDFium itself matches 180 exactly and all 182 within 1%. We judged each of the fork's 50 misses against the PDF specification. PDFium is the more correct in 19 and the fork in 6. In 24 both are acceptable, mostly damaged files the specification gives no answer for, and in 1 both are wrong. Where the fork is wrong, it's mostly in recovering damaged files, plus a few missing features such as generating an appearance for annotations and form fields that don't include one. Full results, the conformance runs and how they were measured. Each miss, judged against the specification.
What it costs
What the design costs, and what isn't finished yet.
- Not quiet enough at idle. In these tests, six of GNOME's eight apps didn't wake up at all while idle. Aizome's woke between about one and nine times a second (its system monitor more often), and the shell about 53 times. Every app checks its settings file once a second (about 0.02 ms of CPU each time), the system-service watchers each check for a stop request four times a second, Shiori's watchdog keeps ticking even when no page is being drawn, and the blinking cursors in Sumi, the text editor, and Hotaru, the terminal, never stop. None of these costs much on its own, but together they keep CPU cores from reaching their deepest sleep states. Simple fixes would take most of them to zero.
- No shared libraries. Each app is a single Rust program with the toolkit compiled in, 13–24 MB on disk. Two Aizome apps running side by side each load their own copy of the toolkit code (10–13 MiB each), where two GTK apps would share one.
- Pictures stay in RAM. Because the shell draws on the CPU, its bar, Deskbar and desktop are pictures in system memory, so a bigger screen costs RAM: at 3840 × 2160 the shell held 16 MiB more private memory than at 1920 × 1080. Its wallpaper is an 8 MiB picture, but it costs the shell about 24 MiB.
- The shell grew over a long session. Over four unattended hours, the live shell's private memory went from 372 MiB to 693 MiB, and it kept growing more slowly, to about 785 MiB nine hours later. The growth is in its worker threads' allocator arenas, and a freshly started shell uses 55 MiB. We haven't tracked down the cause yet.
- Copying to the GPU. For CPU-drawn windows, the compositor has to upload whatever changed to the GPU, while a GL client's buffer is already there. Damage tracking keeps those uploads small, but a terminal scrolling every frame still costs the compositor about twice as much as Ghostty does.
- Terminal latency and throughput. Hotaru shows a keystroke about a frame later than foot or GNOME's terminals, and the latest Ghostty reads output faster (terminals).
How it was measured
Everything was measured on one machine, an AMD Ryzen 7 9800X3D (8 cores, 16 threads) with 62 GiB of RAM, its built-in Radeon graphics, and an NVIDIA RTX 5090 driving a 3840 × 2160 display, running Sekka on Linux 7.3. Every program we compared came from Sekka's own Nixpkgs, at the same versions a Sekka install would get, except Ghostty's main branch, which we built. Each ran with Sekka's default settings unless a section says otherwise.
Only one measurement ran at a time, and each one held a lock that kept other tests and builds off the machine. Programs took turns rather than running all of one and then all of the next, each started with an unmeasured warm-up run, and the figures shown are medians. A desktop has no battery to measure, so power came from the CPU socket's own sensor (PPT, which covers the cores, the Radeon graphics and the I/O die), cross-checked against its RAPL energy counter.
These are measurements of headless compositors and virtual machines rather than of light coming off a real screen, and they all come from a single machine. The dataset's README explains how each one was taken, and the data and test harnesses sit next to it in the repository.
Versions of everything measured
| Software | Version |
|---|---|
| Aizome (compositor, shell and apps, including Hotaru, Utsushi and Shiori) | 0.1.0, Sekka d7ecbac |
| Shiori's renderer, hayro (Aizome's fork), and upstream hayro | a2e9e62b, 04a801de |
| Sekka's Nixpkgs, where everything else comes from | 26.11 (1c89083) |
| Linux, systemd | 7.3.0, 262 |
| Mesa (Radeon), NVIDIA driver | 26.2.6, 615.78.08 |
| GNOME Shell, Mutter, GDM | 50.4, 50.5, 50.2 |
| GTK 4, libadwaita, GTK 3 (gnome-terminal), VTE | 4.22.4, 1.9.3, 3.24, 0.84 |
| GNOME's apps (Calculator, Clocks, Loupe, Papers, Files, System Monitor, Disk Usage Analyzer, Console) | 50.0–50.2.2 |
| GNOME Text Editor, gnome-terminal | 50.1, 3.60.0 |
| KDE Plasma (KWin, Plasma Login), Plasma System Monitor | 6.8.2 |
| KDE Frameworks, Qt | 6.31.0, 6.12.0 |
| KDE's apps (Konsole, Dolphin, KCalc, KWrite, Gwenview, Okular, Filelight) | 26.08.2 |
| Ghostty (release, main) | 1.4.0, 1.4.1-dev 0b1729e |
| foot | 1.28.0 |
| sway (the neutral compositor), wlroots | 1.12, 0.20.2 |
| mpv, libplacebo | 0.41.0, 7.360.1 |
| VLC | 3.0.24 |
| FFmpeg (Utsushi and mpv; VLC) | 9.0.2; 8.1.3 |
| PDFium (GCC build, AGG renderer) | 8110 |
| MuPDF | 1.28.5 |
| Poppler, Cairo | 26.10.0, 1.18.4 |
| QEMU (the VMs) | 11.1.2 |