- store codepoints by reference in RenderCell (accessor still clones on
read); the constructor clone double-allocated every cell and defeated
the shared-empty-array optimization
- return rows as an unmodifiable view instead of List.copyOf; the list is
a fresh local that never escapes
- preallocate row/cell lists to known rows/cols capacity
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each per-field cell getter wrapped its own Arena.ofConfined() (a native
alloc/free plus session bookkeeping) to hold a few output bytes. With ~6
downcalls per cell that is tens of thousands of confined arenas per frame on a
full screen, which profiling in jprototerm pinned as ~6-7ms/frame and the
dominant render cost.
Allocate the scalar out-segments (int, bool, color, style) plus a growable
graphemes buffer once per snapshot in a single Scratch, confined to the
single marshalling thread, and thread it through the cell getters. Also drop a
redundant List.copyOf of the per-row cell list (RenderRow's constructor already
makes the immutable copy) and reuse a shared empty-codepoints array.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>