Message ID | 20190309024944.zcbwgvn52jsw2a2e@dcvr (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | bitmaps by default? [was: prune: use bitmaps for reachability traversal] | expand |
On Sat, Mar 09, 2019 at 02:49:44AM +0000, Eric Wong wrote: > Jeff King <peff@peff.net> wrote: > > Pruning generally has to traverse the whole commit graph in order to > > see which objects are reachable. This is the exact problem that > > reachability bitmaps were meant to solve, so let's use them (if they're > > available, of course). > > Perhaps this is good impetus for doing bitmaps by default? I'm actually not sure it is, because the prune costs less than making the bitmaps. Here are some timings on linux.git. This full-graph traversal is roughly the same cost as the reachability walk that prune would do internally: $ time git rev-list --objects --all >/dev/null real 0m47.714s user 0m47.113s sys 0m0.600s Here's a normal noop repack as a baseline. $ time git repack -ad real 1m26.922s user 1m20.029s sys 0m7.878s And here's another immediately after with bitmap generation. Generating the bitmaps takes about 100s, compared to the 47s it would save us on the prune. $ time git repack -adb real 3m5.915s user 2m59.377s sys 0m7.718s Things are a little rosier if you generate the bitmaps a second time: $ time git repack -adb real 1m43.571s user 1m37.403s sys 0m8.179s We can reuse some of the old bitmaps and it only takes 20 extra seconds, making it a net win. But I'm not sure how realistic that is. There were literally no new objects introduced between those two command. If this were a "real" repack occurring after we'd accumulated a week or two worth of objects, how long would it take? A few other random observations: - I do suspect there are some real inefficiencies in the way we generate bitmaps. It _should_ be about as expensive as the graph traversal, but clearly it's not. I think this is because of the way the current bitmap code picks commits to bitmap, and then walks somewhat haphazardly over the history, trying to accumulate the set of objects for each commit. IOW, I believe it may sometimes traverse over some sequences of history more than once. So if we could make that faster, then the balance would shift in its favor. - This is comparing the cost of generating the bitmaps to the time saved for _one_ operation. On a repo serving many fetches, the cost to generate it is amortized over many requests. But for a normal end-user, that's not true (they'd presumably push out their work, but that usually only needs to walk a small bit of history anyway). The balance would change if we had more operations that used bitmaps (e.g., --contains can use them, as can ahead/behind checks). We don't do those things yet, but we could. However, those algorithms are also using other commit-graph optimizations, and we've discussed revamping the bitmap format as part of that work (one problem in particular is that to use the current bitmaps you have to parse the whole .bitmap file, making it sometimes a net negative to use the bitmaps). So I'd consider holding off any decision like "let's make this the default" until we see where that work goes. > It would make life easier for people new to hosting git servers > (and hopefully reduce centralization :) I do think they're a net win for people hosting git servers. But if that's the goal, I think at most you'd want to make bitmaps the default for bare repos. They're really not much help for normal end-user repos at this point. > I started working on it, but t0410-partial-clone.sh fails with > "Failed to write bitmap index. Packfile doesn't have full > closure"; so more work needs to be done w.r.t. default behavior > on partial clones... Yeah, you can't use bitmaps at all in an incomplete clone. Shallow clones would probably have the same issue (though in general we just disable bitmaps entirely in shallow situations, so that might kick in). -Peff
diff --git a/builtin/repack.c b/builtin/repack.c index 67f8978043..ca98d32715 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -14,7 +14,7 @@ static int delta_base_offset = 1; static int pack_kept_objects = -1; -static int write_bitmaps; +static int write_bitmaps = -1; static int use_delta_islands; static char *packdir, *packtmp; @@ -344,10 +344,14 @@ int cmd_repack(int argc, const char **argv, const char *prefix) die(_("--keep-unreachable and -A are incompatible")); if (pack_kept_objects < 0) - pack_kept_objects = write_bitmaps; + pack_kept_objects = write_bitmaps > 0; - if (write_bitmaps && !(pack_everything & ALL_INTO_ONE)) - die(_(incremental_bitmap_conflict_error)); + if (!(pack_everything & ALL_INTO_ONE)) { + if (write_bitmaps > 0) + die(_(incremental_bitmap_conflict_error)); + } else if (write_bitmaps < 0) { + write_bitmaps = 1; + } packdir = mkpathdup("%s/pack", get_object_directory()); packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid()); @@ -368,7 +372,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argv_array_push(&cmd.args, "--indexed-objects"); if (repository_format_partial_clone) argv_array_push(&cmd.args, "--exclude-promisor-objects"); - if (write_bitmaps) + if (write_bitmaps > 0) argv_array_push(&cmd.args, "--write-bitmap-index"); if (use_delta_islands) argv_array_push(&cmd.args, "--delta-islands");