From 3205fbd5b55d493ce5154280d65a6a524cd949aa Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 1 Sep 2026 00:22:55 -0400 Subject: [PATCH 1/2] ref(opt): scale Clay element capacity with the terminal grid Clay preallocates its arena from a fixed default of 8192 max elements, so an 80x24 terminal reserved 4.85 MB of linear memory before rendering anything. Element capacity drives nearly all of Clay_MinMemorySize (~600 B/element on wasm32); the measure-text word cache is second-order. Derive the cap from the grid instead: 2x cells, clamped to [2048, 8192]. Leaf elements occupy at least one cell and internal nodes with branching >= 2 can at most double the leaf count, so 2x cells bounds realistic trees while leaving headroom for floating elements and wrapper chains. The ceiling keeps large grids at exactly today's capacity; the floor protects tiny panes. Arena for 80x24 drops 4.85 MB -> 2.39 MB (-51%); 20x5 bottoms out at 1.23 MB; 200x50 is unchanged. Render benches are flat. The capacity setters run at the top of both clayterm_size() and init() so the size the host queries always matches what init consumes, for the first init and for in-place re-init alike: Clay_MinMemorySize prefers the live context's caps and Clay_Initialize inherits them from the old context, so the update() resize flow (#113) sizes correctly in both directions. Verified against a local merge of nm/feat/resize: full suite passes, and renders stay error-free across 80x24 -> 200x50 -> 20x5 -> 132x43 in-place resizes. Exceeding the cap degrades the same way it always has, just at the new boundary: Clay stops opening elements and the frame surfaces an error through RenderResult.errors. --- src/clayterm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/clayterm.c b/src/clayterm.c index a0b7d43..c1edb83 100644 --- a/src/clayterm.c +++ b/src/clayterm.c @@ -552,7 +552,24 @@ static Clay_SizingAxis decode_axis(uint32_t *buf, int len, int *i) { static int align64(int n) { return (n + 63) & ~63; } +/* Clay's element capacity drives nearly all of Clay_MinMemorySize, so scale it + * with the grid instead of shipping Clay's fixed 8192-element default. 2x cells + * bounds sane trees (leaves >= 1 cell, branching >= 2); the ceiling preserves + * today's capacity for large grids, the floor keeps headroom on tiny ones. + * Must run before Clay_MinMemorySize in both clayterm_size and init so the + * size the host queries always matches the arena init consumes. */ +static void set_clay_capacity(int w, int h) { + int elems = w * h * 2; + if (elems < 2048) + elems = 2048; + if (elems > 8192) + elems = 8192; + Clay_SetMaxElementCount(elems); + Clay_SetMaxMeasureTextCacheWordCount(elems * 2); +} + int clayterm_size(int w, int h) { + set_clay_capacity(w, h); int cell_count = w * h; int cell_bytes = cell_count * (int)sizeof(Cell); int out_bytes = cell_count * OUT_BYTES_PER_CELL; @@ -613,6 +630,7 @@ int error_message_ptr(struct Clayterm *ct, int index) { } struct Clayterm *init(void *mem, int w, int h) { + set_clay_capacity(w, h); struct Clayterm *ct = (struct Clayterm *)mem; int cell_count = w * h; int cell_bytes = align8(cell_count * (int)sizeof(Cell)); From 07b986bfcd97f38a1d3d97f106f4e0a3292e8647 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Tue, 1 Sep 2026 16:52:16 -0400 Subject: [PATCH 2/2] chore: add changeset for grid-scaled arena --- .changeset/grid-scaled-arena.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/grid-scaled-arena.md diff --git a/.changeset/grid-scaled-arena.md b/.changeset/grid-scaled-arena.md new file mode 100644 index 0000000..f1a5cad --- /dev/null +++ b/.changeset/grid-scaled-arena.md @@ -0,0 +1,5 @@ +--- +'@bomb.sh/tty': patch +--- + +Scales the renderer's memory arena to the terminal grid instead of a fixed default, cutting the reservation for an 80×24 grid ~51% (4.85 MB → 2.39 MB) with no change to render performance.