Skip to content

D-WAL: LanceCycleWriter vs MemWAL measured; capped session cache, version clock, copy-free temporal projections - #1562

Merged
AdaWorldAPI merged 19 commits into
mainfrom
ccr-9f3b8075-74u47l-wal-shootout
Oct 15, 2026
Merged

AdaWorldAPI merged 19 commits into
mainfrom
ccr-9f3b8075-74u47l-wal-shootout

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Plan: .claude/plans/wal-shootout-v1.md. Board entry: .claude/board/entries/2026-10-15-d-wal-shootout.md.

Measured

D-id What was measured Result
D-WAL-1 Validation of both arms Both write paths are crash-atomic per cycle and lose nothing they acknowledged. MemWAL needs durable_write = true for that. Its acknowledged writes are visible only to the writing handle until a flush or a WAL replay.
D-WAL-2 Commit cost With the default 100 ms flush, every MemWAL write waits about 95 ms. With a 10 ms flush it is faster than LanceCycleWriter from 1,024 casts per cycle.
D-WAL-3 Soak (stopped at 27.5 min by a container restart) MemWAL commit p50 stayed flat at 2.0–2.8 ms; L grew from 5.8 to about 10.5 ms. MemWAL's disk use was 1.57× L's. L's RSS grew from 95 to 762 MiB.
D-WAL-4 Where L's RSS growth comes from It is Lance's session metadata cache, not our writer. Each commit caches a clone of that version's manifest, and in this append-only store manifest v lists v fragments, so the cache grows as V²/2. At 1,600 versions: 628 MiB with the default session, 7.8 MiB with an 8 MiB cap. RSS 570 vs 52 MiB.

Changes

  • D-WAL-5 — capped session. LanceCycleWriter now opens and writes on a Lance session whose metadata cache is capped at 8 MiB (SESSION_METADATA_CACHE_BYTES).
    • Written test-first. 400 commits reached 42.6 MB uncapped. With the cap the cache stays under 8 MiB, after reopening as well.
    • Removing the session from the create write turns the test red, and so does removing it from open.
  • D-WAL-6 — version clock. New contract type temporal_pov::{VersionClock, ClockError}.
    • It records the row count at each version of an append-only lane, eight bytes per version.
    • rows_at(&TemporalPov) returns one half-open row range: 4.2 ns per call on an AVX-512 host, against 127 µs for a per-row scan of 400k rows.
    • Tested against a per-row oracle over 200 versions, including skipped versions and versions that add no rows.
    • Three disable runs each turn a test red: no gap fill, an off-by-one start, no base guard.
    • Not yet wired into a writer or reader.
  • D-WAL-7 — copy-free projections. temporal.rs gains deinterlace_indices, local_trajectories_indices and local_trajectory_indices_of. They return positions into the input and clone no row. The copying functions keep their signatures and wrap the index forms.
  • D-LNC-7 — decision. L stays the default with the capped session; MemWAL stays an option. The 60-minute soak is deferred.

Verification

  • Every build ran with debug info 0.
  • Tests: lance-graph-contract 1483, lance-graph-planner 458, lance-graph 1058 (lib), all passing.
  • Clippy -D warnings passes on every changed target. It still fails on two existing files this PR does not touch: planner/examples/probe_r2il_real_episodes.rs and planner/tests/moore_nars16_probe.rs.

Still open

  • Seeding the version clock from storage when a writer opens an existing store.
  • Compaction or deletes break the prefix property the clock relies on, so they need a fragment-id remap.
  • The full-length soak (deferred).

🤖 Generated with Claude Code

https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2c821d27-163b-4f45-b1c6-ec96009684e1
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review October 15, 2026 06:30
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T06:33:41.055183Z 12319fe Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12319fef8b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/lance-graph/tests/wal_shootout_probe.rs Outdated
Comment thread crates/lance-graph/tests/wal_shootout_probe.rs
Comment thread crates/lance-graph-planner/src/temporal.rs
claude added 19 commits October 15, 2026 06:45
… MemWAL (D-WAL-1..3)

Validation (SIGKILL atomicity, acknowledged => durable, idempotent resubmit,
read horizon), cost per cycle and per row, and a 60-minute soak per arm.
Feeds D-LNC-7 without deciding it. AGENT_LOG records the three mapper runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
… 0.40 MemWAL path; D-WAL-2/3 harness

Shared harness writes the same logical cycle on both arms; gated on
lancedb-sdk. lancedb rejects UInt64 as a primary key, so M's pk is Int64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…d; MemWAL writes invisible to other readers until flush or replay

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…e cycle sizes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
Maps the spec's atomicity, durability, recovery, visibility, fencing,
compaction and GC rules onto the measured V1-V4 and cost results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…tate

The soak stopped at 27.5 min / 1,649 cycles when the container
restarted. MemWAL commit p50 stayed flat at 2.0-2.8 ms while
LanceCycleWriter's grew from 5.8 to about 10.5 ms over 1,649 versions.
MemWAL keeps its WAL after each flush (1.57x the disk). Both scans
grow linearly in rows; LanceCycleWriter's RSS grew 95 -> 762 MiB, not
yet explained.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…pped session)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…, measured

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
… metadata cache

Every Lance commit caches a manifest clone per version; in this append-only
store that grew as V^2/2 (D-WAL-4). Test-first: 400 commits reached 42.6 MB
on the default session; with the cap the cache stays under 8 MiB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…o array reads

Eight bytes per version; row-version oracle test over 200 versions with gaps
and empty versions; seeded clocks refuse versions before their base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…s at 400k rows)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…orms become wrappers

deinterlace_indices / local_trajectories_indices / local_trajectory_indices_of
return positions into the input (4 B per row) and clone nothing; the existing
copying functions keep their signatures and map the indices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…ession field)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…, VersionClock in the contract inventory

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…mber (citation-decay)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…tures; temporal index forms refuse > u32::MAX rows

CI runs 'cargo test --test *', and cargo refuses an explicitly selected
target whose required features are off. The index forms of deinterlace and
local trajectories now panic instead of wrapping when the input exceeds
u32::MAX rows (Codex P2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
…arget ACK

V1 sweeps kill delays from 0 ms to 10 s and asserts the sweep produced both a
landed and an empty store; before, a one-sided sweep only printed
INCONCLUSIVE and passed. V2 asserts the child acknowledged the target cycle
before the kill; before, a child that died early left nothing to recover and
the recovery checks passed vacuously.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
@AdaWorldAPI
AdaWorldAPI force-pushed the ccr-9f3b8075-74u47l-wal-shootout branch from 683d247 to e38779f Compare October 15, 2026 07:16
@AdaWorldAPI
AdaWorldAPI merged commit 31ef180 into main Oct 15, 2026
18 checks passed
AdaWorldAPI added a commit that referenced this pull request Oct 15, 2026
board: #1562 merged (D-WAL) — PR arc entry and LATEST_STATE
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.

2 participants