From 100efa22a9a2bb82b85c95fa2ce933311ca09ee3 Mon Sep 17 00:00:00 2001 From: Kristofer Karlsson Date: Thu, 9 Jul 2026 16:26:57 +0200 Subject: [PATCH 1/2] commit-graph: add trace2 instrumentation for generation DFS Count the number of steps taken in compute_reachable_generation_numbers() and expose it via trace2 to make it easier to detect performance regressions. Add a failing test for such a regression, introduced in 199d452758 (commit-graph: return the prepared commit graph from `prepare_commit_graph()`, 2025-09-04), where incremental commit-graph writes do not see existing generation numbers from lower graph layers and fall back to walking the full ancestry. Signed-off-by: Kristofer Karlsson --- commit-graph.c | 5 +++++ t/t5324-split-commit-graph.sh | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/commit-graph.c b/commit-graph.c index c6d9c5c740e94d..702ba9731b0ed7 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1653,6 +1653,7 @@ static void compute_reachable_generation_numbers( { int i; struct commit_list *list = NULL; + intmax_t steps = 0; for (i = 0; i < info->commits->nr; i++) { struct commit *c = info->commits->items[i]; @@ -1671,6 +1672,7 @@ static void compute_reachable_generation_numbers( int all_parents_computed = 1; timestamp_t max_gen = 0; + steps++; for (parent = current->parents; parent; parent = parent->next) { repo_parse_commit(info->r, parent->item); gen = info->get_generation(parent->item, info->data); @@ -1694,6 +1696,9 @@ static void compute_reachable_generation_numbers( } } } + + trace2_data_intmax("commit-graph", info->r, + "generation-dfs-steps", steps); } static timestamp_t get_topo_level(struct commit *c, void *data) diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index 49a057cc2eb65d..b41331e3dd930c 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -718,6 +718,30 @@ test_expect_success 'write generation data chunk when commit-graph chain is repl ) ' +test_expect_failure 'incremental write reads topo levels from all layers' ' + git init topo-from-lower && + ( + cd topo-from-lower && + + for i in $(test_seq 5) + do + test_commit base-$i || return 1 + done && + git commit-graph write --reachable && + + test_commit extra && + git commit-graph write --reachable --split=no-merge && + + git checkout base-3 && + test_commit new-branch && + + GIT_TRACE2_EVENT="$(pwd)/trace.txt" \ + git commit-graph write --reachable --split=no-merge && + + test_trace2_data commit-graph generation-dfs-steps 1 Date: Thu, 9 Jul 2026 16:26:57 +0200 Subject: [PATCH 2/2] commit-graph: propagate topo_levels slab to all chain layers The topo_levels slab is only propagated to the topmost graph layer instead of all layers in the chain. Commits from lower layers appear to have no generation numbers, so the DFS re-walks the entire ancestry. Fix by making topo_levels visible to all layers, not just the first one. Signed-off-by: Kristofer Karlsson --- commit-graph.c | 2 +- t/t5324-split-commit-graph.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/commit-graph.c b/commit-graph.c index 702ba9731b0ed7..a0bca248ac9cee 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -2610,7 +2610,7 @@ int write_commit_graph(struct odb_source *source, g = prepare_commit_graph(ctx.r); for (struct commit_graph *chain = g; chain; chain = chain->base_graph) - g->topo_levels = &topo_levels; + chain->topo_levels = &topo_levels; if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS) ctx.changed_paths = 1; diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index b41331e3dd930c..9e5ab7dbd07553 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -718,7 +718,7 @@ test_expect_success 'write generation data chunk when commit-graph chain is repl ) ' -test_expect_failure 'incremental write reads topo levels from all layers' ' +test_expect_success 'incremental write reads topo levels from all layers' ' git init topo-from-lower && ( cd topo-from-lower &&