Skip to content

persist: stream HNSW node blobs in bounded windows; compact/persist progress logs - #46

Merged
andreimarinescu merged 2 commits into
mainfrom
andrei/persist-streaming
Aug 31, 2026
Merged

persist: stream HNSW node blobs in bounded windows; compact/persist progress logs#46
andreimarinescu merged 2 commits into
mainfrom
andrei/persist-streaming

Conversation

@andreimarinescu

Copy link
Copy Markdown
Collaborator

PersistFrom materialized every encoded node blob before writing the first
byte (hnsw_persist.go:84-90) — the 1 GiB chunking inside
PutVectorNodesBatch bounds the Pebble batch, not the caller's entries
slice. On the production graph that is ~240 GB of transient heap on top of
the ~250 GB live graph: a full persist cannot complete on the box, it
OOM-kills first. That makes /admin/hnsw-compact destructive as shipped —
the handler durably wipes the v family before persisting, so the OOM
would land in the window where the RAM copy is the only copy. (Full persist
has never completed at production scale; the on-disk graph was built by the
60 s incremental checkpoints. The shutdown final persist hits the same wall,
silently.)

Fix. PersistFrom now encodes and flushes in ~1 GiB windows, releasing
each window before the next; peak extra heap is ~2 windows regardless of
graph size. Meta is still written once, after all windows — the
meta-lags-nodes crash invariant is unchanged.

Observability. Multi-window persists log progress (hnsw persist: N/M nodes (X GiB, rate, eta)); single-window persists (the incremental
checkpoints) stay silent, so no journal noise at the 60 s cadence.
Compact()'s write-locked scan/rewire phases log every 10M nodes — during
that phase /stats blocks on the same lock, so these lines are the only
liveness signal a supervising operator has.

…rogress logs

Full persist materialized every encoded node blob before writing — ~240 GB
of transient heap at the production graph size, an OOM before the first
byte lands. hnsw-compact wipes the on-disk graph before persisting, so
that OOM would leave no graph on disk. PersistFrom now encodes and
flushes in ~1 GiB windows (meta still written last, preserving the
meta-lags-nodes crash invariant) and logs progress with rate and ETA on
multi-window persists. Compact's write-locked phases log every 10M nodes
so a supervised run is observable while /stats is blocked on the lock.
@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@andreimarinescu
andreimarinescu merged commit 61e28ff into main Aug 31, 2026
5 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