@matheusbsbs / matheus-bagliano / commits / e369698016
Fork 0

diff: halt tree-diff early after max_changes

When computing the changed-paths bloom filters for the commit-graph, we limit the size of the filter by restricting the number of paths in the diff. Instead of computing a large diff and then ignoring the result, it is better to halt the diff computation early. Create a new "max_changes" option in struct diff_options. If non-zero, then halt the diff computation after discovering strictly more changed paths. This includes paths corresponding to trees that change. Use this max_changes option in the bloom filter calculations. This reduces the time taken to compute the filters for the Linux kernel repo from 2m50s to 2m35s. On a large internal repository with ~500 commits that perform tree-wide changes, the time reduced from 6m15s to 3m48s. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Garima Singh <garima.singh@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Mar 30, 2020 at 00:31 UTC e3696980163bdbd3bc56e5ffc69e8770015f366f
3 files changed +14 -1
bloom.c
+3 -1
@@ -133,6 +133,7 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
133 struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS;
134 int i;
135 struct diff_options diffopt;
136 + int max_changes = 512;
137
138 if (bloom_filters.slab_size == 0)
139 return NULL;
@@ -141,6 +142,7 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
142
143 repo_diff_setup(r, &diffopt);
144 diffopt.flags.recursive = 1;
145 + diffopt.max_changes = max_changes;
146 diff_setup_done(&diffopt);
147
148 if (c->parents)
@@ -149,7 +151,7 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
151 diff_tree_oid(NULL, &c->object.oid, "", &diffopt);
152 diffcore_std(&diffopt);
153
152 - if (diff_queued_diff.nr <= 512) {
154 + if (diff_queued_diff.nr <= max_changes) {
155 struct hashmap pathmap;
156 struct pathmap_hash_entry *e;
157 struct hashmap_iter iter;
diff.h
+5
@@ -285,6 +285,11 @@ struct diff_options {
285 /* Number of hexdigits to abbreviate raw format output to. */
286 int abbrev;
287
288 + /* If non-zero, then stop computing after this many changes. */
289 + int max_changes;
290 + /* For internal use only. */
291 + int num_changes;
292 +
293 int ita_invisible_in_index;
294 /* white-space error highlighting */
295 #define WSEH_NEW (1<<12)
tree-diff.c
+6
@@ -434,6 +434,9 @@ static struct combine_diff_path *ll_diff_tree_paths(
434 if (diff_can_quit_early(opt))
435 break;
436
437 + if (opt->max_changes && opt->num_changes > opt->max_changes)
438 + break;
439 +
440 if (opt->pathspec.nr) {
441 skip_uninteresting(&t, base, opt);
442 for (i = 0; i < nparent; i++)
@@ -518,6 +521,7 @@ static struct combine_diff_path *ll_diff_tree_paths(
521
522 /* t↓ */
523 update_tree_entry(&t);
524 + opt->num_changes++;
525 }
526
527 /* t > p[imin] */
@@ -535,6 +539,7 @@ static struct combine_diff_path *ll_diff_tree_paths(
539 skip_emit_tp:
540 /* ∀ pi=p[imin] pi↓ */
541 update_tp_entries(tp, nparent);
542 + opt->num_changes++;
543 }
544 }
545
@@ -552,6 +557,7 @@ struct combine_diff_path *diff_tree_paths(
557 const struct object_id **parents_oid, int nparent,
558 struct strbuf *base, struct diff_options *opt)
559 {
560 + opt->num_changes = 0;
561 p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt);
562
563 /*