ReviewOS

home-lang/home

perf(ts): index whole CommonJS export paths for repeated member checks

#848
Open chris opened this 8 days ago ·
8 days ago

Parent #416; related profiling/performance work #839. Current compiler source 206cdf1, byte-identical inputs on main 3698c7a. Diagnostic-only relink of exact cached ReleaseFast object has byte-identical machine-code section and passes all 56 frozen/diagnostic admission records. One-second commonJS scale1024 stack sample shows repeated reportProgramRequireBindingMissingMember -> programImportTargetsPath/stripProgramModuleExtension work. Source programCommonJsModuleHasWholeExport linearly scans every whole-export record for each query; the scale importer has many require bindings and typed member reads. This is general immutable metadata work, not a benchmark/name-specific shortcut.

Required candidate: lazy canonical whole-export path index; preserve exact extension-normalized external OR fallback path matching, duplicates, misses and empty/named-only tables. Rebuild on setProgramCommonJsExports; never transfer TypeIds or discard diagnostics. Preserve shared source/resolver/importer invalidation contracts and allocation-failure behavior. Add semantic and algorithmic reuse/reset controls; full checker/Program/CLI and pinned production identity gates. Same-parent stripped ReleaseFast A/B on unchanged official CommonJS plus same-generator scale and all-family screens, retain adverse intervals and predeclared rechecks. Fresh admitted competitor matrix, detailed docs/raw evidence and brief README table before new performance claims. No speedup or source fix claimed yet. Local profile/provenance /Users/chris/.cache/home-ts-perf-next.QX4Fk4.

8 days ago

Implemented a draft lazy extension-normalized whole-export presence set; it stores no foreign TypeIds and leaves named/type schema lookup untouched. Shared import-resolution helper retains external OR fallback answers exactly as before. setProgramCommonJsExports clears/rebuilds the set; deinit releases it. New controls exercise duplicate paths, misses, empty/named-only tables, metadata replacement, importer changes and resolver changes. Full checker 4503/4503 passed under unchanged guard (3389 MB observed). Native build is live; no timing, commit or speed claim yet. Diagnostic image passed all 56 frozen/diagnostic admissions and current samples showed the general linear whole-export scan in CommonJS member checking.

8 days ago

Independent unchanged-input confirmation supports a local CommonJS gain: official median 29.823 -> 28.327 ms, 26/30 faster pairs, paired mean saving interval +0.218 to +1.856 ms; same-generator scale1024 449.598 -> 373.946 ms, 10/10, +65.470 to +86.664 ms. Initial official screen interval crossed zero; retained. All-family screen warns startup (>3% slower median, interval crossing zero) and large predicates (>3% slower, negative interval); both selected for independent 30-pair rechecks, now live/queued. No universal no-regression claim. Full checker 4503 and Program 238 passed; complete pinned Zod multiset unchanged at 195 TS + 3 HM9002. Entrypoint gate live. Fresh five-compiler 20-workload matrix queued with all existing positive/negative admissions, pinned provenance and unchanged limits. Candidate not committed/pushed yet; new performance claims require recheck/matrix/docs/raw evidence.

8 days ago

Independent confirmation supports the local gain: official CommonJS 29.823 -> 28.327 ms (26/30 faster pairs, saving CI +0.218 to +1.856 ms); scale1024 449.598 -> 373.946 ms (10/10, +65.470 to +86.664 ms). Full checker 4503, Program 238, entrypoint 35 and full pinned Zod identity gate pass (195 TS + 3 HM9002 unchanged). However all-family large-predicate screen and selected recheck both warn: recheck 266.922 -> 270.431 ms, 8/30 faster pairs, saving interval -6.510 to -0.496 ms. Startup recheck is near-flat with interval crossing zero. Retaining both warnings; not accepting or labeling the candidate regression-free. Fresh five-compiler matrix is live and all 140 admissions passed. Next investigate/reduce lazy-index storage footprint/initialization effects on unrelated files with a separately frozen variant; no benchmark-specific special case, limits unchanged. No source push yet.

8 days ago

The first inline-index candidate remains unaccepted because large predicates had adverse intervals in both screen and independent recheck. Retained its entire fresh five-compiler result 20261008T140417Z (all 140 admissions, all 600 rounds / 3000 samples); do not present it as an accepted current snapshot. A separately frozen variant now stores the lazy index behind a nullable pointer instead of adding an inline hash table/built flag to every checker. Source checks that never query whole CommonJS paths allocate no index; setProgramCommonJsExports still invalidates it and deinit owns/releases it. This is a general storage change, not a benchmark-name special case. Same semantic controls retained; full checker/native build live/queued under unchanged limits. No commit or speedup claim for the variant yet.

8 days ago

Nullable lazy-index variant full checker 4503 passes; complete Zod identities still unchanged (195 TS + 3 HM9002). Same-parent official confirmation 30.088 -> 28.531 ms, 29/30 faster pairs, saving CI +0.699 to +2.262 ms; scale1024 453.839 -> 379.511 ms, 10/10, +59.207 to +81.697 ms. All-family screen still flags startup/reexports/generic calls (>3% slower medians), so independent 30-pair rechecks are queued. Also carry forward large predicates because the prior inline variant had an independently confirmed negative interval; not treating its absence from this variant threshold list as clearance. Entrypoint live, candidate uncommitted. The inline full matrix 20261008T140417Z is retained as unaccepted evidence, not current results; no mixing cross-variant observations or benchmark-specific compiler branch.

8 days ago

Rejected both compiler index variants after retaining every observation. Inline variant large-predicate recheck: 266.922 -> 270.431 ms, 8/30 faster pairs, saving CI -6.510 to -0.496 ms. Nullable lazy variant: 279.147 -> 283.733 ms, 9/30, -6.528 to -1.070 ms. Both still had positive official CommonJS confirmation, but the adverse unrelated-family evidence is not dismissed or best-of-selected. Restored the compiler implementation; rebuilt native SHA-256 is exactly the parent 7346fd7bbc264c20a9b32a0da08e8579e615e68795c961f4f91911e6b276063a. Only two general path-matching/reset controls remain, full checker 4503/4503 passed. Committed as Chris without coauthors: 9bc9c91 test(ts): retain whole-export path controls after perf rejection (#848); pushing main in this chunk. Both patches/binaries/samples/profiles and the entire unaccepted matrix 20261008T140417Z remain intact for evidence publication. Its archive is bench/vs_tsgo/evidence/20261008T140417Z-rejected-848.tar.gz; it is not the accepted current performance snapshot. Next: investigate a design that retains the general CommonJS gain without the observed tradeoff, with fresh independent controls. Detailed rejection report and brief README table are the next publication chunk.

8 days ago

The first push of the retained-controls commit was rejected because main advanced; no force push used. Integrated ab5d774/10a2a8c/17b4508 cleanly, preserving upstream config/conformance work, and rebased test-only commit is c52ec0e. The rejected index production changes are absent; only the two general path-matching/metadata-replacement controls remain. Previous restored build exactly matches frozen parent SHA7346; that equivalence refers to source3698 before the unrelated incoming config/resolver changes, not a claim about the newly integrated runtime. Evidence remains source-pinned. Detailed rejection/evidence/README publication is pending and the full goal is still incomplete.

8 days ago

Main advanced again during the second normal push attempt, so it was rejected without changing the remote. Integrated a85f89e (test/conformance variant work), rebased the test-only retained-controls commit to 773ca88 and retried a normal main push. No force push, coauthors or rejected compiler optimization. Both indexed variants remain unaccepted; evidence/README rejection-report chunk is next. All experiment results stay pinned to original source3698 and their frozen hashes rather than being relabeled as measurements of this integrated tree.

8 days ago

Published the rejection report/README table and both verified archives as Chris without coauthors: 686089a docs(ts): preserve rejected CommonJS index evidence (#848). Normal push initially rejected after main advanced; cleanly rebased onto 5ed5168 and retried without force. Paired/profile archive retains 686 pair rounds, seven phases / 392 admissions, 56 diagnostic-image admissions and 7031 verified checksums (SHA256 a54ace54f9e3a5f991cc04149e082cd4e4e8948c72e76589002aac0740b96e73). Separate rejected matrix 20261008T140417Z retains 600 rounds / 3000 samples, 140 admissions, 603 checksums (SHA256 6052b7d07edbdfbe7e2356a74b4803486e0aaa55a5d02890d0360f3030feea74). All medians/win counts/negative intervals and archive bytes verified; edited docs pass targeted pickier. Both variants remain rejected: ~5% CommonJS gain alongside independently adverse large-predicate rechecks (1.3%/1.6% slower). Restored compiler behavior, retained only path-matching tests in 773ca88. Unaccepted matrix Home leads 1/20; do not relabel it current or infer a new accepted win. No root cause asserted for the unrelated-family cost. Next logical work must remove that tradeoff, not rerun until favorable or add benchmark-specific conditions. Report: https://github.com/home-lang/home/blob/main/docs/docs/TS_PERFORMANCE.md#whole-commonjs-path-indexes-rejected-2026-10-08-utc

8 days ago

Publication correction: the push of local docs commit 686089a was rejected because main advanced again; earlier publication wording was premature. After a clean rebase onto 9e98f42 (including f25b1c8/07f774b/028386f), the normal push succeeded. The actual published commit is 9ccd62c, docs(ts): preserve rejected CommonJS index evidence (#848), authored/committed as Chris without coauthors. Remote main was verified at that commit and the worktree is clean. Both archives and their checksums are unchanged. Rejected candidates remain source3698-pinned, not claimed as measurements of the newer integrated compiler. README tradeoff table and detailed report are now genuinely on origin/main: https://github.com/home-lang/home/blob/main/docs/docs/TS_PERFORMANCE.md#whole-commonjs-path-indexes-rejected-2026-10-08-utc

8 days ago

Accepted compiler implementation and retained evidence are now on main, pushed as Glenn without coauthors:

  • 3c397539e — perf(ts): index CommonJS export paths (#848)
  • 5976d10d3 — docs(ts): retain CommonJS index evidence (#848)

Design: Program stamps source order and stably canonicalizes its owned CommonJS export table once by extension-normalized path. Checkers borrow that slice and binary-search matching ranges. Private metadata still selects the lowest original source index across external/fallback matches. There is no per-checker allocation, new limit, foreign TypeId, benchmark-name branch, or test weakening.

Final-source gates:

  • checker 4,509/4,509
  • Program 242/242
  • driver 200/200
  • CLI 74/74
  • tsc_main 35/35
  • 56 official + 4 scale admissions passed; scale negatives remained exactly TS2322×3 + TS2339×3 on both binaries
  • pinned Zod 4.5.2: identical normalized 195 TS + 3 HM9002 output across 106 files, SHA-256 b605370c…e4e5c
  • maximum guarded footprint 3,097 MB under the unchanged 3,840 MB ceiling

Exact-parent stripped ReleaseFast evidence (three warmups, fresh processes, alternating order, no filtered samples):

PhaseParentCandidateResult
Official CommonJS, 30 pairs34.325 ms33.478 ms25/30 wins; saving CI +0.429 to +1.255 ms
Scale-1024 first retained phase573.819 ms486.144 ms7/10; CI crosses zero after two candidate outliers
Scale-1024 independent follow-up563.116 ms473.763 ms30/30 wins; saving CI +79.260 to +93.304 ms
Deep-types independent recheck25.462 ms25.678 msCI −0.390 to +0.227 ms
Large-predicate independent recheck306.698 ms310.473 msCI −12.206 to +3.980 ms

All 20 family screens are retained; every unrelated-family interval spans zero. The noisy first scale phase remains evidence and was not replaced.

Detailed report: https://github.com/home-lang/home/blob/main/docs/docs/TS_PERFORMANCE.md#program-owned-canonical-commonjs-export-table-accepted-2026-10-08-utc

Raw archive: https://github.com/home-lang/home/raw/main/bench/vs_tsgo/evidence/20261008T165919Z-commonjs-sorted-table-848.tar.gz — 360 paired rounds, 64 admissions, exact runners/logs/source, 385 verified payload checksums; SHA-256 ee3d55e06172a84f34f7a5264ccd3ba0d6a6a509b3d04f15bf13f121b2a5f68f.

The fresh expanded matrix is not claimed complete. The exact tsc-rs archive verified, but the moving Bun-canary download no longer matched the checked-in bd599f5af archive pin, so I recorded zero matrix samples and made no substitution. Because this issue explicitly requires an admitted fresh matrix, I am leaving it open and linking the remaining provenance work to #838. The next matrix must also add the active C++ TypeScript port under the same pinned schema/admission rules.

Sign in to comment on this issue.