Skip to content

fix(storage): scale the payload chain budgets with the cutoff (#472) - #479

Merged
yifanxuaaa merged 1 commit into
mainfrom
fix/chain-budget-scales-with-cutoff
Oct 27, 2026
Merged

yifanxuaaa merged 1 commit into
mainfrom
fix/chain-budget-scales-with-cutoff

Conversation

@yifanxuaaa

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #472 / #473. The payload chain-work budgets were fixed at 512 KiB canonical and 256 KiB encoded, while the construction cutoff can be raised to 1 MiB. Before #473, a whole file above those sizes failed the next Save. After #473 it is stored FULL, so a Store with a raised cutoff gets no whole-file deltas for files of about 256 KiB or more: every version is a complete copy.

  • The budgets are now 4 × cutoff canonical and 2 × cutoff encoded (StorageCapacities::from_policy). At the default 128 KiB cutoff that is exactly 512 KiB / 256 KiB, so default Stores do not change.
  • At every supported cutoff, the largest whole file fits a chain alone, so the producer never stores a base that a read could not charge, and large whole files keep deltas.
  • Trade-off (owner-approved): one read may reconstruct up to 4 × cutoff, which is 4 MiB at the 1 MiB cutoff. That is the same ratio to the largest whole file that the default Store already accepts. A depth never raises the budgets. Chunk chains (32 KiB chunks) stay depth-bound and are unaffected, so chunked files of any size behave as before.
  • fix(storage): store FULL when a delta base alone exceeds the chain budget #473's early refusal stays as a guard. Valid output under a Store's own policy no longer reaches it.
  • No schema or format change. Components must be version-matched (release policy). Upgrade note: existing Stores with a raised cutoff start producing whole-file deltas after upgrade. Their existing chains already fit the larger budgets.

Tests

Side finding (not changed here)

At zstd level 3 with no long-distance matching, highly repetitive text (word salad from eight words) loses the delta to FULL even for a 10-byte edit: the matcher takes nearby repeats over the long match into the base. CSV-like text deltas normally, and the SDK delta tests use that. This is codec behavior and independent of the budgets.

Test plan

  • Fail-before against main 924f782 production code: chain_budget_scaling 1 passed / 5 failed; sdk_large_file_budget 2 passed / 3 failed (work_exceeded, FULL, no delta). With the fix, all pass.
  • layerfs-storage 93 passed; layerfs-persistence 118 passed, 2 ignored; layerfs-project 23; layerfs-store-service 6.
  • Fast-lane selection (tools/ci_tests.py) per package: layerfs-api 45 binaries, 138 passed, 6 ignored; layerfs-daemon 9 binaries, 24 passed, 1 ignored. Run package by package because cargo-nextest is not installed locally and the worktree launcher refuses workspace aggregates.
  • Clippy -D warnings (storage, api, all targets), cargo fmt --check, tools/check_product_boundary.py, 155 tool tests.
  • Not run: Linux, mounted FUSE Commit, Windows, read latency/memory at the deepest 4 MiB chain. Durable: NOT_RUN — disabled by owner until explicit reauthorization.

All runs were on macOS arm64, Rust 1.85.1, through tools/worktree.py private resources, with Disposable Stores only.

Production LOC: 102,580 -> 102,588 (delta +8). core 38,387 -> 38,395; layerfs-storage 9,060 -> 9,068 (store/policy.rs 179 -> 187); engine 61,534 and api 2,659 unchanged. Reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). Method: tools/production_loc.py (blob 3341e4d036) --detail/--files --root on a git archive of 924f782 and on this tree.

Generated with Devin

The payload chain-work budgets were fixed at 512 KiB canonical and 256 KiB
encoded while the construction cutoff may be raised to 1 MiB. A whole file
above those sizes then failed the next Save (#472); after #473 it stores
FULL, so a Store with a raised cutoff gets no whole-file deltas for files
of about 256 KiB or more. The budgets are now 4 x cutoff canonical and
2 x cutoff encoded. At the default 128 KiB cutoff they are exactly
512 KiB / 256 KiB, so default Stores do not change. At any supported cutoff
the largest whole file fits a chain alone, so the producer never stores a
base a read could not charge, and large whole files keep deltas. The cost
is read work: one read may reconstruct up to 4 x cutoff (4 MiB at 1 MiB).
A depth never raises the budgets; chunk chains stay depth-bound. #473's
early refusal stays as a guard; valid output under a Store's own policy
no longer reaches it.

Tests: chain_budget_scaling (new) covers the derived budgets, the
largest-file-fits invariant, #472's shapes now chaining, the largest file
at each cutoff and a chain restarting at the scaled budget.
delta_base_budget moves its still-valid prospective boundaries, one-save
parity and corruption guard to the default cutoff, where the same numbers
hold, and reaches the early refusal by lowering the fixture's cutoff after
the base is stored. Its five 1 MiB "base alone over budget" cases are
deleted: under scaled budgets they now chain, re-covered positively.
sdk_large_file_budget now asserts a delta for fs.apply, fs.write and a
Workspace Commit (CSV-like text; word salad from eight words loses to FULL
at zstd level 3), keeps Init and the default-cutoff control.

Validation, macOS arm64, Rust 1.85.1, worktree launcher, Disposable only:
- Against main 924f782 production with these tests:
  chain_budget_scaling 1 passed / 5 failed; sdk_large_file_budget
  2 passed / 3 failed (work_exceeded FULL, no delta). With the fix all pass.
- layerfs-storage 93 passed; persistence 118 passed, 2 ignored; project 23;
  store-service 6; fast-lane binaries of layerfs-api (45: 138 passed,
  6 ignored) and layerfs-daemon (9: 24 passed, 1 ignored).
- Clippy -D warnings (storage, api), fmt, boundary guard, 155 tool tests.
Not run: Linux, mounted FUSE Commit, Windows, read-latency/memory
measurement at the 4 MiB chain. Durable: NOT_RUN - disabled by owner
until explicit reauthorization.

Production LOC: 102580 -> 102588 (delta +8)
  core 38387 -> 38395; layerfs-storage 9060 -> 9068 (store/policy.rs
  179 -> 187). engine 61534 and api 2659 unchanged. Reference absent
  (retired R9c; last counted 65,417 at tree 498dd19).
  Method: tools/production_loc.py (blob 3341e4d) --detail/--files
  --root on a git archive of 924f782 and on this tree.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@yifanxuaaa
yifanxuaaa merged commit 08ded82 into main Oct 27, 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