Skip to content

[energy] Memoize per-frame FFI/geometry - #394

Merged
gregoreesmaa merged 3 commits into
mainfrom
energy/385-memoize-ffi
Oct 4, 2026
Merged

gregoreesmaa merged 3 commits into
mainfrom
energy/385-memoize-ffi

Conversation

@gregoreesmaa

Copy link
Copy Markdown
Owner

Memoizes per-frame FFI/geometry that scroll frames re-derive every tick (#385). Caller-owned zero-alloc tables; every miss path is bit-identical to the old direct call.

What changed

  • mathBox (viewport.zig): 8-entry memo keyed (tex ptr/len, font_px, display), threaded via ViewportConfig/FlowCtx/UnitCx into islands, display lines, and math fences. Refusals latched. Null cache = old direct call, so metrics passes and all existing tests are untouched.
  • Fence extents: fence_end stamped per plugin row at open/seeding (pluginStampFenceEnds); render/height/refine share codeFenceEnd (inline-scan fallback for non-plugin fences). pluginFenceGeom stops at the first row past the query (rows are fence-ordered).
  • highlight.tokenize: 16-entry memo keyed (lang, line ptr/len) on the render path only; null (plain-run) outcome latched.
  • gatedImageSize (main.zig): 16-entry (url -> w/h) memo per document generation, reset on every open; metrics+draw share it.
  • Find: monotone warm-start floor for the per-run binary search (reset per frame); visited-link single-slot memo per frame.
  • mouseMoved (macos.m): single block pass (button + container hit, proven same outcome), cached link_url_len (no strlen per hover). onScroll takes the NSEvent timestamp as a trailing FFI double (clock fallback) instead of clock_gettime per callback. platform.h updated to match.

Tests

  • 5 new viewport parity tests (memo-vs-direct incl. FFI call counts, refusal latch, tokenize incl. null, fence ends, ordered lookup) + 1 main stamping test.
  • src/core/strict_benchmarks.zig untouched (no target loosened).

Evidence / platform-blocked gaps (Windows host, honest)

  • zig build test -Doptimize=ReleaseFast --summary all: only the 17 pre-existing POSIX-gated errors, byte-identical set on the clean tree (verified via stash); hot module 13/13 green; zero errors in touched files. Standalone memo-contract harness 2/2 green; highlight 11/11, bidi 3/3, remote_policy 6/6 green.
  • NOT runnable here (need macOS): full zig build test green, ./scripts/size_gate.sh + twin-delta, sh scripts/damage_parity.sh, screenshot regeneration. CI must confirm all four before merge. New BSS is ~5 KiB (MathBoxCache ~288 B, TokenCache ~2.3 KiB, image memo ~4.3 KiB latched entries are BSS so ship-file cost is ~0, but the gate must still prove it).

gregoreesmaa added a commit that referenced this pull request Oct 3, 2026
…can fallback (#394 fix-round)

Pre-existing test broke: hand-built PluginEntry tables (fence_end defaults 0) hit codeFenceEnd, which trusted fence_end=0 as the fence close. scan_i=0 collapsed code_line_count/consumed, so the ready image box never grew document height. Original path inline-scanned to the real close (2). Fix: honor stamped ends only (fence_end > fence_line), else break to the bit-identical inline scan. New-table parity test uses stamped ends, unaffected. 0 is provably never a valid stamp (ends are > fence_line >= 0).
gregoreesmaa added a commit that referenced this pull request Oct 4, 2026
…can fallback (#394 fix-round)

Pre-existing test broke: hand-built PluginEntry tables (fence_end defaults 0) hit codeFenceEnd, which trusted fence_end=0 as the fence close. scan_i=0 collapsed code_line_count/consumed, so the ready image box never grew document height. Original path inline-scanned to the real close (2). Fix: honor stamped ends only (fence_end > fence_line), else break to the bit-identical inline scan. New-table parity test uses stamped ends, unaffected. 0 is provably never a valid stamp (ends are > fence_line >= 0).
@gregoreesmaa
gregoreesmaa force-pushed the energy/385-memoize-ffi branch from e782e92 to 39c299e Compare October 4, 2026 08:58
gregoreesmaa added a commit that referenced this pull request Oct 4, 2026
…can fallback (#394 fix-round)

Pre-existing test broke: hand-built PluginEntry tables (fence_end defaults 0) hit codeFenceEnd, which trusted fence_end=0 as the fence close. scan_i=0 collapsed code_line_count/consumed, so the ready image box never grew document height. Original path inline-scanned to the real close (2). Fix: honor stamped ends only (fence_end > fence_line), else break to the bit-identical inline scan. New-table parity test uses stamped ends, unaffected. 0 is provably never a valid stamp (ends are > fence_line >= 0).
@gregoreesmaa
gregoreesmaa force-pushed the energy/385-memoize-ffi branch from 39c299e to b43a51e Compare October 4, 2026 09:29
gregoreesmaa added a commit that referenced this pull request Oct 4, 2026
…can fallback (#394 fix-round)

Pre-existing test broke: hand-built PluginEntry tables (fence_end defaults 0) hit codeFenceEnd, which trusted fence_end=0 as the fence close. scan_i=0 collapsed code_line_count/consumed, so the ready image box never grew document height. Original path inline-scanned to the real close (2). Fix: honor stamped ends only (fence_end > fence_line), else break to the bit-identical inline scan. New-table parity test uses stamped ends, unaffected. 0 is provably never a valid stamp (ends are > fence_line >= 0).
@gregoreesmaa
gregoreesmaa force-pushed the energy/385-memoize-ffi branch from 38bff1b to 3082335 Compare October 4, 2026 15:56
Render/height/refine re-derived per-frame FFI/geometry every scroll
tick. Memoize with caller-owned, zero-alloc tables; miss paths are
bit-identical to the old direct calls:

- mathBox: 8-entry memo keyed (tex ptr/len, font_px, display) wired
  through ViewportConfig/FlowCtx/UnitCx (islands, display lines,
  math fences); refusals latched. Null cache = old direct call.
- fence extents: fence_end stamped per plugin row at open/seeding;
  render/height/refine share codeFenceEnd (inline scan fallback).
  pluginFenceGeom stops at first row past query (fence-ordered).
- highlight.tokenize: 16-entry memo keyed (lang, line ptr/len),
  null outcome latched; render path only.
- gatedImageSize: 16-entry (url -> w/h) memo per document,
  reset on open; metrics+draw share.
- find: monotone warm-start floor for the per-run binary search,
  reset per frame; visited-link single-slot memo per frame.
- mouseMoved: single block pass (button + container hit), cached
  link_url_len (no strlen per hover); onScroll takes NSEvent
  timestamp (trailing FFI double, clock fallback) instead of
  clock_gettime per callback.

Tests: 5 new viewport parity tests (memo-vs-direct, refusal latch,
tokenize incl. null, fence ends, ordered lookup) + 1 main stamping
test. strict_benchmarks.zig untouched.

Platform-blocked on this host (Windows): zig build test shows only
the 17 pre-existing POSIX-gated errors (identical set on clean
tree); hot module 13/13 green; size_gate/damage_parity/screenshots
need macOS - CI must confirm.
…can fallback (#394 fix-round)

Pre-existing test broke: hand-built PluginEntry tables (fence_end defaults 0) hit codeFenceEnd, which trusted fence_end=0 as the fence close. scan_i=0 collapsed code_line_count/consumed, so the ready image box never grew document height. Original path inline-scanned to the real close (2). Fix: honor stamped ends only (fence_end > fence_line), else break to the bit-identical inline scan. New-table parity test uses stamped ends, unaffected. 0 is provably never a valid stamp (ends are > fence_line >= 0).
@gregoreesmaa
gregoreesmaa force-pushed the energy/385-memoize-ffi branch from 3082335 to 39935f2 Compare October 4, 2026 16:09
@gregoreesmaa
gregoreesmaa merged commit 343b4f1 into main Oct 4, 2026
3 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