diff options
author | Derrick Stolee <dstolee@microsoft.com> | 2018-05-01 12:47:17 +0000 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-05-22 12:36:34 +0900 |
commit | f9b8908b85247ef60001a683c281af0080e9ee77 (patch) | |
tree | 2c686d90564dfc810cff7c47e0b895a6e562d1ef | |
parent | ref-filter: use generation number for --contains (diff) | |
download | tgif-f9b8908b85247ef60001a683c281af0080e9ee77.tar.xz |
commit: use generation numbers for in_merge_bases()
The containment algorithm for 'git branch --contains' is different
from that for 'git tag --contains' in that it uses is_descendant_of()
instead of contains_tag_algo(). The expensive portion of the branch
algorithm is computing merge bases.
When a commit-graph file exists with generation numbers computed,
we can avoid this merge-base calculation when the target commit has
a larger generation number than the initial commits.
Performance tests were run on a copy of the Linux repository where
HEAD is contained in v4.13 but no earlier tag. Also, all tags were
copied to branches and 'git branch --contains' was tested:
Before: 60.0s
After: 0.4s
Rel %: -99.3%
Reported-by: Jeff King <peff@peff.net>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | commit.c | 9 |
1 files changed, 8 insertions, 1 deletions
@@ -1056,12 +1056,19 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit * { struct commit_list *bases; int ret = 0, i; + uint32_t min_generation = GENERATION_NUMBER_INFINITY; if (parse_commit(commit)) return ret; - for (i = 0; i < nr_reference; i++) + for (i = 0; i < nr_reference; i++) { if (parse_commit(reference[i])) return ret; + if (reference[i]->generation < min_generation) + min_generation = reference[i]->generation; + } + + if (commit->generation > min_generation) + return ret; bases = paint_down_to_common(commit, nr_reference, reference); if (commit->object.flags & PARENT2) |