Repository navigation
Build rows lazily: components, minimum_spanning_forest, vector_topk, most_similar - #63
Merged
Merged
Conversation
components, minimum_spanning_forest, vector_topk and most_similar built every row's external id before returning the first, in the call's multi-call memory context: about 72 bytes a text id, held until the call ended (0.72 and 1.38 GB at 10M nodes). They now return an iterator over the kernel's result, still in the extension's own buffer, and the loaded version, and make each row's ids in next(), in the per-row context Postgres resets. A pg_test for each opens a cursor on the call and checks that what it holds after its first row does not grow with the rows to come: 3.6 to 7.3 MB more for 50,000 rows before, now none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
In every shared cache mode: a call stopped early, a cursor read across statements after its version is evicted, a call that errors mid-scan and one cancelled between rows each return what they should and leave no version held. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
The text peaks of components and minimum_spanning_forest fall to what the version's size alone accounts for (0.84 and 1.10 GB from 1.28 and 1.77 at 5M nodes). Lists the SRFs that already streamed and the two that still build their rows up front. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
# Conflicts: # DESIGN.md # bench/results/soak/README.md
The full-scale text paragraph now says its components and minimum_spanning_forest peaks were measured before rows were made as they are returned, and points to the half-scale re-measure. walk and neighbours, which still build their rows up front, are noted with why and listed for M11. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
This was referenced Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
These four SRFs built every row's external-id datum up front in the SRF's multi-call context, which holds it until the call ends. That cost about 72 bytes per id on text graphs, which showed in the full-scale soak (#62).
They now return a boxed iterator over the kernel's result (still in the extension's own
try_reserved buffer) and theArc<LoadedVersion<E>>. Each row's ids are built innext(), in the per-row context Postgres resets between rows, asbfs,vector_valuesandgatheralready do.TDD: a
#[pg_test]for each function compares the memory held by a 50k-row call and a 1k-row call. On main the 50k-row call held 3.6 MB (7.3 MB for the forest) against 0.13–0.17 MB; it now holds less than 256 kB more.test/sql/shared_cache_lazy_rows.sql, in all three cache modes:LIMIT;warren.evict;After each case, nothing is left in use or held.
Half scale (5M nodes), peaks with text ids:
components1.28 → 0.84 GB,minimum_spanning_forest1.77 → 1.10 GB. Times are unchanged.DESIGN.md §12 and §13: the fix is described as implemented.
walkandneighboursstill build rows up front, bounded by their limits and by a node's degree; they're listed for M11 with the reason.Local gate: fmt, clippy, rustdoc; core 702; pgrx PG16 775 / PG18 776;
run.pyPG16 62/62 in all three modes;dump.pyok.Generated by Claude Code