commit cost — before and after incremental dimension commitments
Date: 2026-10-15. Scope: bbg 441e3c9 (origin/master) → branch
fix/launch-43-incremental-commit. Tracker: cyber/launch.md row 43 (blocks
row 14, the bostrom genesis replay). Prior finding: cybergraph
audit/import-commit-cost-2026-09-27.md — every accepted operation recommitted
every dimension from its full record set, so a chain's cost was quadratic in its
length.
what changed
- every committed dimension is a
Keyedmap (KeyedSetfor N,AxonIndexfor adjacency) that keeps a canonical keyed trie (rs/src/trie.rs) current on every mutation and caches its v1 Brakedown commitment until it mutates; RootVersion::V1(default) folds the Brakedown leaves — bit-exact with the previous root, only dimensions touched since the last read are recommitted;RootVersion::V2folds the trie roots — a block costs O(changes · log n);max_degreeis maintained by the adjacency index, not scanned per root.
Spec: specs/state.md § BBG root, § root versions, § dimension commitment v2.
method
rs/examples/commit_cost.rs N B [v1|v2]: N synthetic one-link signals from
1,000 neurons, sources uniform over N/2 particles, targets Zipf-like over N/4
(hubs), one block per B = 100 links, root materialized at every block edge.
rs/examples/replay_pussy.rs CSV [v1|v2]: the pussy snapshot
(~/.cache/snapshots/pussy/cyberlinks_indexed.csv.gz, 29,112 cyberlinks,
114 neurons), one block per source height (17,696 blocks). Release build, one
thread, M4 Max; peak memory = /usr/bin/time -l "peak memory footprint".
Wall time is the whole run including state construction.
results
synthetic, 100 links per block
| links | v1 (before) wall | v1 µs/link | v2 (after) wall | v2 µs/link | v2 peak memory |
|---|---|---|---|---|---|
| 10,000 | 39.6 s | 3,964 | 5.7 s | 572 | 20 MB |
| 100,000 | stopped at 60,000 links after 1,661 s (the curve below extrapolates the full run to ≈ 1.6 h) | 48,594 at 60k | 69.6 s | 696 | 182 MB |
| 1,000,000 | not run (the curve below extrapolates to > 1 day) | — | 847.8 s | 848 | 1.94 GB |
Per-10k-link cost along the run (the curve, not the average):
| links done | v1 µs/link (100k run) | v2 µs/link (1M run) |
|---|---|---|
| 10,000 | 5,834 | 588 |
| 20,000 | 14,938 | 659 |
| 30,000 | 24,216 | 762 |
| 40,000 | 30,138 | 703 |
| 50,000 | 42,358 | 716 |
| 60,000 | 48,594 | 728 |
| 100,000 | — | 757 |
| 500,000 | — | 837 |
| 1,000,000 | — | 874 |
v1 grows linearly with the state (each 10k adds ≈ 8 s per 10k), so the chain is quadratic; v2 grows with log n only (the trie depth), ≈ 10 % per decade.
(v1 per-10k numbers are from the 100k run, which shared the machine with builds for its first minutes; the standalone 10k run is the 39.6 s above.)
pussy snapshot, one block per height
| mode | links | blocks | wall | µs/link | peak memory | root |
|---|---|---|---|---|---|---|
| v1 (before) | 29,112 | 17,696 | stopped at 10,000 links after 183 s (20.3 s for the first 5k, 163 s for the next 5k) | 32,605 at 10k and rising | — | — |
| v2 (after) | 29,112 | 17,696 | 21.0 s | 723 | 63 MB | 90517c16…2218c |
cost model after
Per touched record: one leaf chain (1 + ⌈fields/4⌉ compressions) plus two compressions per branch on its path (depth ≈ log₂ n). A one-link signal touches particles ×2, axons_out (outer leaf + inner set), axons_in (same), neurons ×1, balances ×2 ≈ 8 paths ≈ 300 hemera permutations ≈ 0.6–0.9 ms on one M4 Max core. Projection for the bostrom replay (2,949,732 links): ≈ 45 minutes single-threaded; the spacepussy-test log (39,060 signals): under one minute. Both inside the row-43 bounds (one day / ten minutes).
Headroom, in order: hash the branch with one permutation over
[tag, bit, 0, 0 ‖ l ‖ r ‖ 0⁴] instead of two compress4 (−45 % per path;
a different in-circuit row shape than the root fold, so it needs zheng's
word); batch the neurons[ν].focus updates of a multi-link signal into one
leaf write; parallelize dimensions.
root
v1 roots are unchanged: tests/root_vectors.rs pins five roots computed on
441e3c9 before the change (empty, one link, one link finalized, every
dimension populated, same finalized) and they hold. All 64 unit tests, the
look-argument e2e and the wire tests pass without modification.
v2 roots differ from v1 by construction (different leaf derivation) and are pinned too. Properties checked: incremental root == from-scratch root of the final record set after 40 random batches with double-spend rejections and block finalization; after pruning and reinsertion; replay reproduces every per-block root; trie paths prove inclusion and non-inclusion against the dimension leaf; v1 ↔ v2 is a view switch on the same records.
No conformance snapshots exist to bless: soft3/conformance is a scaffold
(no .snap files in soft3, bbg or cybergraph on 2026-10-15).
what this does not do
- It does not flip the default. The zheng look argument binds
LookOpening.commitment(a Brakedown cell opening) toleaves.dims[ns]; under v2 that leaf is a trie root and the binding fails by design. v2 becomes the default when zheng opens trie paths (leaf chain + branch chain, the samecompress4rowsbuild_root_stepsalready emits). Until then a node opts in withBbg::with_root_version(RootVersion::V2). - It does not change cybergraph.
prepare_native_batch(cybergraphfeat/durable-applications, bbgfeat/atomic-application-storage) may keep callingrefresh_rootper accepted operation: under v2 that call costs the fold plus the operation's own changes. - Storage is untouched: the tries live in memory next to the maps (v2 1M links: see peak memory above). A node that loads state from storage rebuilds them by inserting through the wrappers, O(n log n) once.