Skip to content

macOS: hidden tabs free their pixel buffers, spare surfaces purgeable (255 MB -> 84 MB with 3 tabs) - #7

Merged
stawan15 merged 1 commit into
developfrom
perf/mac-memory
Sep 28, 2026
Merged

stawan15 merged 1 commit into
developfrom
perf/mac-memory

Conversation

@stawan15

Copy link
Copy Markdown
Owner

litty used 147–168 MB on a Mac with a large window. Almost all of it was copies of the screen: at 1680×992 on Retina each copy is about 27 MB. Every window kept a framebuffer plus up to three IOSurfaces, and on macOS every native tab is a separate window, so hidden tabs paid the full cost too.

Changes

  • Hidden windows free their pixels. A window that is hidden (a background native tab, minimised, or fully covered) drops its framebuffer and surfaces via winit Occluded. When it's shown again it repaints from scratch in one frame. Tab titles and OSC 52 copies still apply while it's hidden.
  • Spare surfaces are purgeable. Once the compositor releases a surface that isn't on screen, it's marked kIOSurfacePurgeableVolatile, so macOS doesn't count it against litty and may reclaim it. If it has been purged, the whole frame is rewritten on next use.
  • Tests no longer read the user's ~/.config/litty/config. Before this, cursor = bar there made cursor_style_requests fail.

Measured (macOS footprint, 1680×992 window, idle zsh)

v0.8.0 this PR
1 tab 100–126 MB 77 MB
3 tabs 255 MB 84 MB

Linux is unchanged: X11 doesn't report occlusion, and softbuffer keeps a single buffer. 83 tests pass on macOS and 82 on Ubuntu, with no new clippy warnings.

Not tested by hand

Switching back to a background tab or un-minimising should repaint in one frame. The numbers above come from footprint on launched windows; nobody has clicked through tabs on screen yet.

…re purgeable

At a 1680x992 Retina window every copy of the screen is ~27 MB: the framebuffer plus up to three
IOSurfaces, in every native tab (each is a window), visible or not.

- A window that is hidden (background native tab, minimised, covered) frees its framebuffer and
  surfaces, and repaints from scratch when it shows again. Titles and OSC 52 still apply meanwhile.
- A visible window marks surfaces it isn't showing as purgeable once the compositor lets go of
  them, so macOS doesn't count them and may take them back; they are rewritten if it does.
- Tests no longer read the user's config file.

Footprint (1680x992 window, idle shell): 1 tab 100-126 MB -> 77 MB, 3 tabs 255 MB -> 84 MB.
@stawan15
stawan15 merged commit 68b09f2 into develop Sep 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant