Repository navigation
Copy compaction pages outside the commit lock - #73
Closed
venkat1701 wants to merge 4 commits into
Closed
venkat1701 wants to merge 4 commits into
venkat1701 wants to merge 4 commits into
Conversation
…r trees TreeWalker.relocate can report every page it reaches, pairMoves maps each old page to its relocated copy, and adopt rebuilds only the nodes written after the snapshot, swapping in copies for everything that moved.
Compaction used to rebuild and write every relocated page inside one rewrite that held the commit lock, so commits stopped for the whole pass. It now relocates and writes the copies from a snapshot without the lock, then takes the lock only to point each branch's latest roots at the copies, rebuilding the few nodes commits wrote in the meantime. The swap commit logs the copies and still advances the relocation fence.
Checks that a commit goes through while compaction copies pages, that commits landing between the snapshot and the swap end up pointing at the copies, that two branches keep their changes and the old segments get deleted, and that a crash at any point of the swap loses nothing.
This was referenced Oct 7, 2026
Collaborator
Author
|
Closing this. #81 replaced tree-rewriting compaction with moving pages through the page directory, so most of this stack no longer applies. A review also found two data-loss bugs in #73 (a retirement generation older than a commit that still used the moved pages, and bulk-loaded pages left behind in a victim). The pieces that still help, the posting list decode, records reused by mapRefs, and the checkpoint crash test, are in #82. |
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.
Closes #50
The problem: compaction rebuilt, encoded and wrote every relocated page inside one
rewritethat held the commit lock, so commits waited for the whole pass (p99 of 2.4 s in the benchmark).The design (as agreed, "copy in background, swap in"):
TransactionManager.relocateworks in three steps.Snapshot under the commit lock for a moment: the latest generation, plus a reserved transaction id.
Copy without the lock:
TreeWalker.relocate, now also recording every page it reaches)pairMoves)Swap under the lock, one branch at a time.
TreeWalker.adoptwalks the branch's latest roots:Only that last kind costs work under the lock. The swap is a normal commit: it logs the copies under the reserved transaction id and moves
relocationFence. Branches created during the copy are swapped too.rewritehad no other callers and is removed. No file-format change, and nothing changes on the read path. Victim choice, segment states, retiring and reclaiming are as before.Known costs:
wal_mode = imagesthe copies' page images are appended to the WAL during the swap, so that mode still does that I/O under the lock. Defaultreferencesmode only logs a small record per page.Results, HStore only, 3 alternating runs each, on the PR stack (#65/#66/#69) with and without these commits. Machine load was about 6. All checksums agree.
Space reclaimed and disk size after compaction are identical (227 / 543 MiB reclaimed). Compaction itself got slightly faster (1.7 to 1.9 s down to 1.4 to 1.7 s).
What's left: the remaining 130 to 330 ms tail is GC, not the lock. A pass allocates 1.7 to 2.1 GiB, causing 2 or 3 pauses of roughly 100 to 350 ms, and each run's worst commit matches its longest pause. Copying pages as raw bytes instead of decoding and re-encoding nodes would cut that. It fits with the allocation work in #56 and #57.
Tested:
./mvnw installpasses (102 tests); each commit compiles on its ownCompactionTest(10 cases), 5 runs in a row:adopt: it then fails with "2175 pages in the current trees still point into compacted segments".mainand a branch during a full compaction are all kept; the old segments are then deleted, and everything reads back, including after reopenPAGE,WAL_APPEND,DATA_WRITE,COMMIT_APPEND,DATA_SYNC,WAL_SYNC,CATALOG_PUBLISH) loses nothingCOMPACTruns through the new path, data unchanged,hstore checkpasses