commit-reach: terminate merge-base walk when one paint side is exhausted#2149
Draft
spkrka wants to merge 5 commits into
Draft
commit-reach: terminate merge-base walk when one paint side is exhausted#2149spkrka wants to merge 5 commits into
spkrka wants to merge 5 commits into
Conversation
Replace the nonstale_queue abstraction in paint_down_to_common() with a new paint_queue struct that tracks per-side commit counts. Each non-stale queued commit occupies exactly one counter bucket based on its paint flags: PARENT1-only, PARENT2-only, or both sides (a pending merge-base candidate). The counters are maintained by paint_count_transition() which handles all flag changes as bucket transfers: remove from the old bucket, add to the new one. Either step is a no-op when the respective state has no bucket (stale or zero). paint_queue_put() atomically updates flags, handles ENQUEUED-based dedup, and adjusts counters. paint_queue_get() pops a commit and decrements its counter. The loop condition changes from pointer-based (while max_nonstale) to counter-based (while any counter is positive), which is equivalent for termination but gives callers precise visibility into the queue composition. The ahead_behind() function continues to use its own insert_no_dup() helper with a single max_nonstale pointer, since it only needs one nonstale dimension and has no per-side tracking. No behavior change. Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Add an early termination check to paint_down_to_common() using the per-side counters introduced in the previous commit. Once the walk enters the finite-generation region (topological order guaranteed by commit-graph), terminate early when one side's exclusive count drops to zero -- no new merge-base can form without both paint sides meeting. The check also waits for pending_merge_bases to reach zero, ensuring all merge-base candidates have been popped and recorded before exiting. This is necessary for FIND_ALL to return all merge bases in criss-cross merge topologies. The INFINITY gate ensures correctness: commits without a commit-graph entry have GENERATION_NUMBER_INFINITY and are ordered by commit date, which is not topologically reliable. The optimization only fires once the walk enters the finite-generation region where ordering guarantees hold. On large repositories with commit-graph, this yields 100-1000x speedups for merge-base queries where one side (e.g. a PR branch) is much smaller than the other. Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Add tests for the case where multiple merge-base candidates exist and one is an ancestor of another. This exercises the side-exhaustion optimization in paint_down_to_common together with the remove_redundant safety net in get_merge_bases_many_0. Test with and without commit-graph to verify the optimization is a no-op when generation numbers are unavailable. Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Add test cases to t6600-test-reach.sh that exercise edge cases in the side-exhaustion optimization for paint_down_to_common(): - in_merge_bases_many:self: commit is both A and one of the X inputs - get_merge_bases_many:duplicate-twos: duplicate entries in X list - get_merge_bases_many:pending-stale: STALE transition on an already-painted commit (ps-* diamond topology) - get_merge_bases_many:infinity-both-sides: both tips outside the commit-graph with non-monotonic dates (pi-* topology) Signed-off-by: Elijah Newren <newren@gmail.com>
Add a perf test that benchmarks merge-base on a synthetic 500k-commit repository with a deep side branch. The test creates a main branch, a side branch forked from an early commit with old timestamps, a merge commit bringing the side branch in, and a PR branch just before the merge. Computing merge-base(main, pr) exercises the side-exhaustion optimization. Includes variants with and without a commit-graph to cover the case where both tips are outside the commit-graph (INFINITY region). Signed-off-by: Kristofer Karlsson <krka@spotify.com>
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.
TBD