Skip to content

terminal: cut the fixed heap cost of a new terminal nearly in half - #14138

Merged
mitchellh merged 4 commits into
mainfrom
vt-mem
Sep 3, 2026
Merged

mitchellh merged 4 commits into
mainfrom
vt-mem

Conversation

@mitchellh

Copy link
Copy Markdown
Contributor

This focuses explicitly on the non-mmap allocations for a ghostty_terminal_new result. The result is that we lower this portion of the memory by almost half. The total benefit is smaller since 70% of a terminal is mmap'd allocations, but this still yields an absolute ~5KB savings on macOS on every new terminal (not just empty, but also with a normal prompt and so on).

Four changes to make it happy, broken down into individual commits. Nothing crazy:

  • Page list nodes are pooled individually. The node pool was a std.heap.MemoryPool, which sits on an arena that preheats and grows 1.5x, so we paid for wasted space. Nodes now come from UntouchedPool (the same pool as page buffers) with a preheat of one, so the cost is exactlyone node (well, exactly one bucket element size in whatever allocator).
  • Pin pool and tracked pin set are sized for two pins. Every screen tracks exactly a viewport pin and a cursor pin at creation, but we preheated eight pins and let the tracked pin map grow to 17 slots on the first insert via doubling.
  • The kitty temp dir path is allocated only when set. The C wrapper embedded a 1 KiB max_path_bytes buffer that only embedders that set kitty_image_medium_temp_file ever wrote to.
  • The default palette is shared instead of copied. DynamicPalette carried two full 1 KiB palettes, current and original, and original was almost always the built-in default. It is now a pointer to the shared built-in default, or to an allocator-owned copy when a custom default is set. This introduces a new OOM path but we gracefully handle it by either ignoring or resetting.

Memory measurements:

Per terminal Before After
phys_footprint delta, fresh 30,066 B 25,069 B
phys_footprint delta, styled prompt written 47,023 B 41,944 B
malloc zone bytes dirtied, fresh 12,698 B 7,782 B
malloc blocks live after terminal_new 11,904 B 6,688 B
malloc blocks live after the prompt 12,320 B 7,104 B

I ran ghostty-bench +terminal-stream on a 500 MB ascii corpus, main vs this branch interleaved, and there is no noticeable change.

AI usage: Fable did validation of the work, I did the implementations, commit messages, and PR notes.

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