refactor: skip no-op edge CSR compaction after COPY - #1071
Open
zhanglei1949 wants to merge 4 commits into
Open
zhanglei1949 wants to merge 4 commits into
zhanglei1949 wants to merge 4 commits into
Conversation
zhanglei1949
force-pushed
the
codex/perf-copy-skip-edge-compact
branch
from
September 14, 2026 07:01
d3cbc3d to
4a7b48e
Compare
zhanglei1949
force-pushed
the
codex/perf-copy-skip-edge-compact
branch
from
September 14, 2026 07:11
4a7b48e to
2db06a9
Compare
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Critical correctness issues remain in MVCC edge marking and unbundled updates, plus a moderate stale-state issue.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This PR optimizes checkpoint finalization by skipping redundant CSR compaction for clean, plain edge tables while preserving required compaction paths.
Changes:
- Tracks and persists edge-table compaction state.
- Adds conservative legacy-manifest fallback behavior.
- Adds C++ and Python persistence and compaction tests.
File summaries
| File | Summary |
|---|---|
tools/python_bind/tests/test_persistence.py |
Tests direct CSV COPY persistence across checkpoint reopen. |
tests/storage/test_edge_table.cc |
Tests mutation tracking and legacy fallback behavior. |
tests/storage/test_ap_index.cc |
Tests persistence and compaction call counts. |
src/transaction/cow_graph_workspace.cc |
Skips compaction for clean plain-edge targets; critical issue remains for MVCC insert/WAL edges bypassing the marker. |
src/storages/graph/edge_table.cc |
Tracks and persists compaction state; critical issue remains because unbundled property updates unnecessarily mark tables dirty. |
src/main/checkpoint_coordinator.cc |
Documents checkpoint finalization behavior. |
include/neug/storages/graph/edge_table.h |
Defines compaction-state tracking; moderate issue remains because CSR rebuild paths do not clear the state. |
Review details
Suppressed comments (2)
include/neug/storages/graph/edge_table.h:220
- The new bit is not cleared by the existing CSR-rebuild paths
dropAndCreateNewBundledCSRanddropAndCreateNewUnbundledCSR: both export only live edges and reinsert them with timestamp 0, but leaveneeds_csr_compaction_unchanged. After an ordinary MVCC mutation followed by edge-property DDL and then COPY, this keeps a now-normalized plain table dirty and causes another redundant compaction, defeating the optimization. Clear the state after these rebuilds (or centralize the reset).
// Batch COPY appends checkpoint-normalized CSR entries at timestamp zero.
// Ordinary writes and deletes require a later CSR scan to normalize
// timestamps or remove tombstones. Persist this bit across incremental
// checkpoint reopen so a later bulk load cannot skip required compaction.
std::atomic<bool> needs_csr_compaction_{false};
src/storages/graph/edge_table.cc:837
- This flag is not updated for every ordinary edge insertion:
GraphView::EdgeTableView::AddEdgewrites throughinsert_edge_into_csr_internaldirectly (src/storages/graph/graph_view.cc:200-205), andMvccInsertTransaction::IngestWaluses that path (src/transaction/mvcc_insert_transaction.cc:239-244). After such an MVCC insert, a later COPY on the same table can seeneeds_csr_compaction_ == falseand skip the required compaction. Route the view insertion through the state-tracking path or propagate the flag intoEdgeTableView.
if (ts != 0) {
needs_csr_compaction_.store(true);
}
- Files reviewed: 7/7 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+672
to
+674
| if (ts != 0) { | ||
| needs_csr_compaction_.store(true); | ||
| } |
Comment on lines
+62
to
+65
| if (!edge_table.NeedsCompaction(sort_key)) { | ||
| continue; | ||
| } | ||
| edge_table.Compact(sort_key); |
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.
Related Issues
Fixes #1069
What does this PR do?
Skips redundant edge CSR compaction for plain timestamp-zero COPY targets while preserving compaction for sort-key tables and edge tables carrying ordinary MVCC writes or deletes.
What changes in this PR?
EdgeTableasneeds_csr_normalization_.EdgeTableView::AddEdgeused by MVCC WAL ingestion; timestamp-zero batch COPY remains normalized.EdgeTable::NeedsCompaction()from both bulk-COPY finalization andPropertyGraph::Compact(), skippingEdgeTable::Compact()only when the target has no sort key and its CSR state is normalized.Why is an EdgeTable-local normalization state necessary?
DirtyTrackerand CSR normalization answer different questions and have independent lifecycles:DirtyTrackercontrols which table modules must be written by a checkpoint and is cleared after an incremental checkpoint.needs_csr_normalization_records whether CSR timestamps or tombstones still require a later O(E) normalization scan; that requirement can survive the checkpoint that clears persistence dirtiness.Keeping the state in
EdgeTablelets the object that owns both CSR directions maintain the invariant at every mutation entry point and persist it across reopen.EdgeTableViewshares that state so view-based WAL ingestion cannot bypass the invariant. Inferring the same fact from CSR contents would require scanning adjacency data and would defeat the optimization.Correctness coverage
EdgeTablemutations andGraphView::AddEdgemark the normalization state, while timestamp-zero view insertion keeps it clear andCompact()resets it.PropertyGraph::Compact()path.Session.Testing
EdgeTableTest.*: 20 tests passed.GraphViewTest.*: 14 tests passed.APIndexTest.*: 30 tests passed.clang-format --dry-run --Werroron the changed C++ files: passed.git diff --check: passed.ENABLE_GCOV=OFFandfastcov/lcovare unavailable.Notes
The optimization is intentionally conservative: sort-key tables always compact, and legacy nonzero checkpoints missing the normalization scalar may perform one extra compaction rather than risk skipping required MVCC normalization.