perf(store): stamp owned backings with $OWNER instead of weak-collection registrations - #3368
Merged
Conversation
🦋 Changeset detectedLatest commit: 5aee76d The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
…ion registrations (#3360) Every backing the store allocates (CoW clones, privatized committed backings) now carries its owning target under an enumerable symbol. This replaces the per-draft ownedRaw.add + raw->target map.set that dominated the one-key write floor (V8 identity hash + ephemeron registration on a fresh object). storeNextLookup / family maps now hold only unowned raws; lookupTarget resolves stamp-first within a family. The stamp is hidden by the get/has/getOwnPropertyDescriptor/ownKeys traps, skipped by snapshot, membership and deep-witness diffs, reconcile, optimistic staging and affects walks, and never acquires a node. Steady-state single-key writes: 340 -> ~178 ns (rc.7 674, rc.0 214). Fixes #3360 Co-authored-by: Claude via Cursor <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com>
ryansolid
force-pushed
the
perf/owned-raw-stamp
branch
from
September 11, 2026 07:33
bea967c to
5aee76d
Compare
Coverage Report for CI Build 34575057520Coverage remained the same at 71.842%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Merging this PR will improve performance by 22.18%
Performance Changes
Tip Curious why performance improved? Comment Comparing |
ryansolid
added a commit
that referenced
this pull request
Sep 11, 2026
`next`'s #3367/#3368 (narrow-store write floor, `$OWNER` stamp) under the A28 seams: createStore 15.15 -> 15.42 KB (15384 B), hydrating + stores 27.90 -> 28.15 KB (28112 B), hydrating 18.48 -> 18.52 KB (18484 B, layout). Core floor unchanged at 22,381. Co-authored-by: Claude via Cursor <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com>
ryansolid
added a commit
that referenced
this pull request
Sep 11, 2026
`next`'s #3367/#3368 (narrow-store write floor, `$OWNER` stamp) under the A28 seams: createStore 15.15 -> 15.42 KB (15384 B), hydrating + stores 27.90 -> 28.15 KB (28112 B), hydrating 18.48 -> 18.52 KB (18484 B, layout). Core floor unchanged at 22,381. Co-authored-by: Claude via Cursor <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part two of #3360 (part one: #3367, merged as 0f14430).
Fixes #3360
Problem
After #3367, the remaining floor of a one-key store write was two weak-collection registrations per draft on a fresh object —
ownedRaw.add(pb)and(fam.map ?? storeNextLookup).set(pb, target). V8 has to assign an identity hash and register ephemerons for each; measured 240–330 ns per pair, i.e. most of the 340 ns write.Change
Every backing the store allocates (CoW clones, privatized committed backings) carries its owning target under an internal enumerable symbol,
$OWNER:cloneRawstamps its output (spread and descriptor paths); overlay drafts (Object.create(v)over an ownedv) inherit the stamp.ensurePB,privatizeCommitted,materializePB,flattenOverlay,drainFoldsno longer touch any weak collection.storeNextLookup/ family maps now hold only unowned raws (user-ingested, adopted).lookupTarget(raw, fam)resolves stamp-first when the owner is in that family, else the map — every former(fam?.map ?? storeNextLookup).getsite uses it.targetsEqualuseslookupTarget(_, null), so plain-store vs family semantics are exactly as before.adoptPBre-stamps a same-family owned adoptee (the stamp is its registration) and maps everything else; reconcile's entity swap disowns the outgoing owned raw so a re-handed raw wraps fresh (proj R10 parity).Because owned raws are never user-reachable (
snapshotcopies them,unwrapis gone in 2.0), the stamp only needs to be hidden inside the store:get/has/getOwnPropertyDescriptoranswer undefined/false for$OWNER;ownKeys(visibleKeys) strips it.membershipChanged(count minus stamp), deep-witness diff, devonStoreNodeUpdatediff,reportReplacedContainers, snapshot copy loops, reconcile symbol pass, optimisticstagedApply/notifyOptimisticWrites/applyTentative, and the legacy affects-scope walk (which now carries the family instead of a map).Numbers (prod dist)
Existing store benches (dev mode, vs #3367): dbmon full/partial tick +30–50%, reconcile tree reverse +84% / shuffle +17%, selection map +33%, overlay delete+set root key +42%, commit boundary +29%, projection root/nested +27% / +8%. Nothing regressed locally.
Tests
tests/store/owner-stamp.test.ts(9): stamp on the committed backing / user object untouched; invisible through every trap incl. spreads (user symbols still enumerate); never insnapshot; never acquires a node or has-node; no spurious membership change on first commit onto an unowned backing; no spurious deep-witness bump on non-plain records or arrays; same-family alias resolves to the same proxy; a store's owned raw handed to a projection stays owned across families (snapshot copies). The membership and deep-witness tests were verified to fail with their guards removed.Gates: signals dev suite green, prod-tier parity (238 baseline), solid 595, web 734, gc test baseline. Size gate: createStore 14.97 → 15.06 KB cap (measured 15.012), hydrating + stores 27.57 → 27.66 KB (27.608), notes in
.size-limit.js.Note on #3367's CodSpeed flag
CodSpeed flagged
createStore setter: delete + set one root key (#3044 overlay)on part one (155.7 → 440.8 µs) with a "different runtime environments" warning. Locally that bench goes next 268k → #3367 464k → this PR 910k ops/s; I could not reproduce a regression with the JIT on and can't run instruction-count simulation here.— Claude via Cursor
Made with Cursor