Skip to content

[energy] Launch/disk I/O: fonts, remote, decode, plugins, Carbon - #395

Merged
gregoreesmaa merged 3 commits into
mainfrom
energy/390-launch-io
Oct 4, 2026
Merged

gregoreesmaa merged 3 commits into
mainfrom
energy/390-launch-io

Conversation

@gregoreesmaa

@gregoreesmaa gregoreesmaa commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

[energy] Launch/disk I/O: fonts, remote re-downloads, decode churn, plugin spawns, Carbon edge. Closes #390. Cold-open I/O diet across five areas; no behavior change (still images, GIF first frames, placeholders, screenshots pixel-identical by construction - confirm via CI suite). FULL BODY FOLLOWS IN COMMENTS - placeholder

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

What changed (all in worktree energy/390-launch-io, 5 files, +521/-49)

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

1. Fonts (macos.m register_app_fonts + bundle scripts) - Resolves Contents/Resources/Fonts bundle-relative FIRST via mainBundle URLForResource, registers only existing paths. Source-relative assets/fonts/* kept as dev fallback. Ship (which never ships top-level assets/) pays zero failed stats; dev keeps working. make_app_bundle.sh vendors the 5 TTFs into Resources/Fonts (data files, never linked - ship __TEXT untouched); check_app_bundle.sh hard-gates their presence. No @embedfile (would cost ~800 KiB __TEXT).

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

2. Remote images (macos.m image_session + ImageFetchDelegate) - New NSURLSessionDataDelegate enforces the remote_policy.zig contract the old session ignored: 8s request/resource timeouts (were 20/30s), MAX_IMAGE_BYTES via didReceiveResponse expectedContentLength cancel + didReceiveData byte counter (was unbounded NSData), max 3 redirects via willPerformHTTPRedirection, no credential/cookie persistence (credentialStorage=nil, cookieStorage=nil, acceptPolicy=Never). Per-task counters live in a static 16-slot ring (no NSDictionary heap churn; >16 concurrent fetches degrade fail-safe to early-cancel placeholders). Session contract probe platform_test_image_session tightened to exact values + delegate non-nil + no-cookie assertions.

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

3. Image decode churn (macos.m loader) - load_image_source_into_record decodes frame 0 only; frames 1..N decode lazily via decode_frame_on_demand (displayed frame +1 prefetch), called from platform_draw_image and gif_advance_frame. A 44-frame GIF now pays 1 decode + 1 prime at load instead of 44+44. Source retained per record (released with it; records are never evicted so no lifecycle change). load_image_sync goes vector-first for .svg/.pdf (skips doomed ImageIO source + frame-0 probe; advisory extension check, still fails closed). Resolved path stored in record at creation - arrivals and platform_arm_images never re-resolve (one resolve per record lifetime). image_load_completed invalidates rect-only via the last drawn rect; off-viewport arrivals skip invalidation entirely. platform_test_image_primed counts decoded frames so primed==total still holds for scroll_profile.sh.

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

4. Plugins (main.zig) - pluginKickForDocument: hasPluginFences fast path before cache-root getenv/job scan/per-job stats (one scan over resident line structs, no bytes walk). pluginWriteShim: hash-skip via pluginFileContentMatches (no rewrite/chmod/mtime churn when bytes identical). New pluginTidyCache(root) per open, before the fence fast path so plain docs clean too: root-derived renderer dirs (cross-session), drops stale probe-.src/.out sentinels, prunes PNGs past 64 files oldest-mtime-first; bounded (256-scan/dir, 32 deletes), best-effort, zero heap (local readdir/stat externs via @extern symbol rename since std.c exposes them Darwin-only; no std.Io/std.fs in ship). pluginJoinPath wraps pluginChildPath (one join codegen site). New unit test pins sentinel matching + join NUL/exactness.

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

5. Launch/Carbon (macos.m + build.zig + main.zig) - Carbon framework link removed from all three link sites; IsSecureEventInputEnabled arrives via dlopen in secure_input_active (cached, fail-open to inactive; dlfcn is libSystem, definition at EOF per SIZE NOTE). All 3 call sites (context menu x2, validateMenuItem) switched with identical truth table. activateMappedFile calls adviseSequential so in-place opens and external reloads get the same SEQUENTIAL+WILLNEED prefetch as cold start.

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

Verification (Windows host - macOS build blocked, done rigorously instead) - Linux-cross zig build test compiles (mod_tests ReleaseFast x86_64-linux-gnu success; only foreign-binary execution fails, pre-existing). Native zig test of the identical tidy algorithm (std.Io variant, same match/prune/delete logic): 3/3 pass - stale sentinels removed, live shim kept, 70 PNGs pruned to exactly 64, content-match exact/mismatch/missing all correct. Notably the harness caught a REAL bug pre-commit: sentinel tail length 10 vs correct 6 (fixed). Exact ship bodies compile for x86_64-macos via build-obj. sh -n clean on both touched scripts. New pure-function unit test added (runs on macOS CI). strict_benchmarks.zig untouched (never loosened).

@gregoreesmaa

Copy link
Copy Markdown
Owner Author

Platform-blocked gaps (need macOS CI) - zig build test -Doptimize=ReleaseFast --summary all (full gate incl. strict benchmarks); ./scripts/size_gate.sh with twin-delta for the PR body (new ship code: tidy + shim-skip + delegate + on-demand fault + secure_input_active; expect small plugin-account growth, core roughly flat minus Carbon load command); screenshot_suite.sh regen + staging + byte-compare; fs_usage cold-open I/O confirmation (fewer stats, no re-downloads, bounded decodes). Screenshots should be pixel-identical by construction: stills decode frame 0 as before, GIF first paint is frame 0, placeholders/rect math unchanged.

Fonts: register_app_fonts resolves Contents/Resources/Fonts bundle-relative first (vendored by make_app_bundle.sh, gated by check_app_bundle.sh); source-relative assets/fonts/* kept as dev fallback. Ship pays zero failed stats; no @embedfile (800 KiB __TEXT untouched).

Remote: NSURLSession delegate enforces remote_policy.zig caps - 8s timeouts, MAX_IMAGE_BYTES via didReceiveResponse cancel + byte counter, 3-redirect cap, no credential/cookie persistence. Session contract probe tightened to exact values.

Images: on-demand GIF frame faults (frame 0 at load, rest at display +1 prefetch); vector-first SVG/PDF path skips doomed ImageIO probe; resolved path stored per record (one resolve per lifetime); arrivals invalidate rect-only, off-viewport arrivals skip.

Plugins: hasPluginFences fast path before root scan/stats; shim hash-skip (no rewrite/chmod churn); per-open bounded tidy (stale probe sentinels + 64-file LRU prune per renderer, root-derived so plain docs clean too).

Launch: Carbon link dropped (IsSecureEventInputEnabled via dlopen, fail-open); adviseSequential in activateMappedFile for in-place opens/reloads.

Platform-blocked here (Windows host): macOS build, size_gate twin-delta, screenshots, fs_usage verification left to CI; Linux-cross core tests compile; new tidy helpers proven via native harness + mac-target build-obj.
…nce_frame use

Implicit decl at :2900 + static-follows-non-static at :2974 broke the
animated-GIF CI build. Declaration hoisted to the top forward block;
definition stays with the loader at EOF. Zero __TEXT impact (decl only).
…e flow (#390)

pluginResolvePaths: collectPluginJobs caps at min(jobs.len, MAX_PLUGIN_JOBS) internally, so the cap/take @min pair was identity - pass jobs straight through and loop to n. The i < bufs.len guard was provably dead (bufs tracks jobs 1:1, 16/16 at all three in-tree callers); index directly. Kick: g_plugin_count = n, the second @min(MAX_PLUGIN_JOBS) was identity on resolvePaths' already-capped return. No behavior change: same bounds, same paths, same NULs; cold path only (no benchmark, screenshot, or scroll impact). Trims ship-only codegen (twin already folds the kick tail away via the hasPluginFences stub). Toward the 110B plugin overrun (CI 37193138258: 17518 vs 17408).
@gregoreesmaa
gregoreesmaa merged commit 824cf19 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.

[energy] Launch/disk I/O: fonts, remote re-downloads, decode churn, plugin spawns, Carbon edge

1 participant