Skip to content

perf(pool): move the claims-journal write off the manager mutex (F1)#6

Merged
CMGS merged 3 commits into
mainfrom
perf/claimstore-writer
Jul 9, 2026
Merged

perf(pool): move the claims-journal write off the manager mutex (F1)#6
CMGS merged 3 commits into
mainfrom
perf/claimstore-writer

Conversation

@CMGS

@CMGS CMGS commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

F1 — claims-journal write off m.mu

claimStore.save marshaled + wrote + renamed the entire claim map while the caller held m.mu, at every claim/release/wake/hibernate/reap. m.mu is the same mutex the data plane takes per exec RTT, so a concurrent claim/wake injected a 1.2–1.9ms stall into every racing data-plane op at 100–1000 live claims (perf audit F1).

Change

  • claimStore splits the write: snapshot() marshals under m.mu + stamps a monotonic sequence; commit() does write+rename off m.mu, serialized by its own mutex and coalescing — an older sequence never overwrites a newer one (sequence order == mutation order, so the newest write wins).
  • The six hot sites (finalizeBatch, Release, reapOnce, commitTransition, archive, commitWake) marshal-under-lock → unlock → commit. Rollback paths re-snapshot + re-commit so disk converges to the rolled-back set on a persist failure.
  • save() wrapper kept for the one non-hot caller (Reconcile, single-threaded startup).

Tests

  • New TestClaimStoreCommitCoalesces (stale snapshot is a no-op) + TestClaimStoreConcurrentCommits (writer off-mutex, -race).
  • Existing durability/persist-failure tests (round-trip, release/reap persistence, archive rollback) unchanged and green.
  • go test -race ./... green; golangci-lint 0 (linux+darwin).

⚠️ Do not merge yet

Durability-core change. Pending: (1) an adversarial review pass, (2) a .52/.79 hardware bench confirming the contention win and no regression (the perf-audit acceptance). Opened now for review while .52 is unreachable.

CMGS added 3 commits July 9, 2026 16:37
claimStore.save marshaled and wrote+renamed the whole claim map while the
caller held m.mu, so every claim/release/wake/hibernate/reap stalled any
concurrent data-plane m.mu acquire for the syscall duration (measured
1.2-1.9ms at 100-1000 live claims). Split it: snapshot() marshals under m.mu
and stamps a sequence; commit() writes off the mutex, serialized and
coalescing (an older sequence never overwrites a newer one). The six hot
sites marshal-under-lock, unlock, commit; rollback paths re-snapshot and
re-commit so disk converges to the rolled-back set.
Adversarial review (an agent + codex) found the six-site write split sound
(coalescing, lock order, seq/written races all verified) with one real edge:
a rolled-back snapshot's best-effort re-commit was discarded, so a double
I/O fault with a concurrent successful commit between them could leave disk
stuck disagreeing with memory until an unrelated later write. Retry the
re-commit so a transient fault converges and a coalesced result counts as
done; a persistent failure warns (memory authoritative + Reconcile on start).
Also correct save()'s doc: Reconcile holds m.mu (startup, uncontended).
BenchmarkStorePersistContention measures a concurrent manager-mutex acquire's
wait during a persist, under-lock (save) vs off-lock (snapshot+commit). Bare
metal .79: 38882->227 ns/acquire @100 claims (171x), 53926->796 @1000 (68x).
@CMGS

CMGS commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Bare-metal F1 proof (.79, Ryzen 9700X, sandbox perf/claimstore-writer)

BenchmarkStorePersistContention — a concurrent manager-mutex acquire's wait during a persist:

live claims under-lock (old save) off-lock (new split) win
100 38882 ns/acquire 226.8 ns/acquire 171×
1000 53926 ns/acquire 796.4 ns/acquire 68×

BenchmarkStoreSaveScaling (persist cost): 16.2µs / 65.7µs / 547.7µs at 10 / 100 / 1000 claims. Also re-ran the full bare-metal e2e regression + archive-lifecycle e2e on .79 against sandbox main — both PASS (warm 0.2–0.5ms, clone 39.8ms, archive wake 37ms). The data-plane stall is smaller in absolute terms on bare-metal NVMe than the mac APFS audit estimate, but the before/after on one harness cleanly shows the m.mu contention removed; it grows with claim count and slower substrates. Ready for merge review.

@CMGS CMGS merged commit a6e1a44 into main Jul 9, 2026
1 check passed
@CMGS CMGS deleted the perf/claimstore-writer branch July 9, 2026 11:29
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