git/builtin
Jeff King 5827a03545 fetch: use "quick" has_sha1_file for tag following
When we auto-follow tags in a fetch, we look at all of the
tags advertised by the remote and fetch ones where we don't
already have the tag, but we do have the object it peels to.
This involves a lot of calls to has_sha1_file(), some of
which we can reasonably expect to fail. Since 45e8a74
(has_sha1_file: re-check pack directory before giving up,
2013-08-30), this may cause many calls to
reprepare_packed_git(), which is potentially expensive.

This has gone unnoticed for several years because it
requires a fairly unique setup to matter:

  1. You need to have a lot of packs on the client side to
     make reprepare_packed_git() expensive (the most
     expensive part is finding duplicates in an unsorted
     list, which is currently quadratic).

  2. You need a large number of tag refs on the server side
     that are candidates for auto-following (i.e., that the
     client doesn't have). Each one triggers a re-read of
     the pack directory.

  3. Under normal circumstances, the client would
     auto-follow those tags and after one large fetch, (2)
     would no longer be true. But if those tags point to
     history which is disconnected from what the client
     otherwise fetches, then it will never auto-follow, and
     those candidates will impact it on every fetch.

So when all three are true, each fetch pays an extra
O(nr_tags * nr_packs^2) cost, mostly in string comparisons
on the pack names. This was exacerbated by 47bf4b0
(prepare_packed_git_one: refactor duplicate-pack check,
2014-06-30) which uses a slightly more expensive string
check, under the assumption that the duplicate check doesn't
happen very often (and it shouldn't; the real problem here
is how often we are calling reprepare_packed_git()).

This patch teaches fetch to use HAS_SHA1_QUICK to sacrifice
accuracy for speed, in cases where we might be racy with a
simultaneous repack. This is similar to the fix in 0eeb077
(index-pack: avoid excessive re-reading of pack directory,
2015-06-09). As with that case, it's OK for has_sha1_file()
occasionally say "no I don't have it" when we do, because
the worst case is not a corruption, but simply that we may
fail to auto-follow a tag that points to it.

Here are results from the included perf script, which sets
up a situation similar to the one described above:

Test            HEAD^               HEAD
----------------------------------------------------------
5550.4: fetch   11.21(10.42+0.78)   0.08(0.04+0.02) -99.3%

Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-10-14 11:31:32 -07:00
..
add.c add: add --chmod=+x / --chmod=-x options 2016-06-07 17:43:39 -07:00
am.c Merge branch 'jk/reset-ident-time-per-commit' into maint 2016-08-12 09:16:56 -07:00
annotate.c
apply.c Merge branch 'rs/apply-name-terminate' 2016-06-03 14:38:04 -07:00
archive.c
bisect--helper.c
blame.c Merge branch 'jk/reflog-date' into maint 2016-09-08 21:35:52 -07:00
branch.c Merge branch 'va/i18n-misc-updates' into maint 2016-05-26 13:17:20 -07:00
bundle.c
cat-file.c Merge branch 'nd/pack-ofs-4gb-limit' into maint 2016-08-08 14:21:36 -07:00
check-attr.c give "nbuf" strbuf a more meaningful name 2016-02-01 13:43:02 -08:00
check-ignore.c give "nbuf" strbuf a more meaningful name 2016-02-01 13:43:02 -08:00
check-mailmap.c strbuf: introduce strbuf_getline_{lf,nul}() 2016-01-15 10:12:51 -08:00
check-ref-format.c use xmallocz to avoid size arithmetic 2016-02-22 14:51:09 -08:00
checkout-index.c checkout-index: disallow "--no-stage" option 2016-02-01 13:43:49 -08:00
checkout.c Merge branch 'rs/use-strbuf-add-unique-abbrev' into maint 2016-09-08 21:36:00 -07:00
clean.c Merge branch 'jk/tighten-alloc' 2016-02-26 13:37:16 -08:00
clone.c Merge branch 'sb/clone-shallow-passthru' into maint 2016-07-11 10:44:12 -07:00
column.c column: read lines with strbuf_getline() 2016-01-15 10:35:07 -08:00
commit-tree.c Merge branch 'jc/commit-tree-ignore-commit-gpgsign' 2016-05-13 13:18:27 -07:00
commit.c Merge branch 'os/no-verify-skips-commit-msg-too' into maint 2016-08-10 11:55:25 -07:00
config.c Merge branch 'jk/config-get-urlmatch' into maint 2016-04-14 18:57:43 -07:00
count-objects.c
credential.c
describe.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
diff-files.c diff: run arguments through precompose_argv 2016-05-13 14:35:49 -07:00
diff-index.c diff: run arguments through precompose_argv 2016-05-13 14:35:49 -07:00
diff-tree.c Merge branch 'ar/diff-args-osx-precompose' into maint 2016-06-06 14:27:35 -07:00
diff.c Merge branch 'ar/diff-args-osx-precompose' into maint 2016-06-06 14:27:35 -07:00
fast-export.c convert trivial cases to ALLOC_ARRAY 2016-02-22 14:51:09 -08:00
fetch-pack.c fetch-pack: fix object_id of exact sha1 2016-03-01 11:19:19 -08:00
fetch.c fetch: use "quick" has_sha1_file for tag following 2016-10-14 11:31:32 -07:00
fmt-merge-msg.c use strbuf_addstr() instead of strbuf_addf() with "%s" 2016-08-05 15:09:25 -07:00
for-each-ref.c ref-filter: add option to match literal pattern 2015-09-17 10:02:49 -07:00
fsck.c Merge branch 'nd/pack-ofs-4gb-limit' into maint 2016-08-08 14:21:36 -07:00
gc.c Merge branch 'ew/gc-auto-pack-limit-fix' into maint 2016-07-28 11:25:56 -07:00
get-tar-commit-id.c usage: do not insist that standard input must come from a file 2015-10-16 15:27:52 -07:00
grep.c Merge branch 'nd/ita-cleanup' into maint 2016-07-28 11:25:51 -07:00
hash-object.c Merge branch 'jk/options-cleanup' 2016-02-10 14:20:08 -08:00
help.c Merge branch 'js/no-html-bypass-on-windows' into maint 2016-09-08 21:35:55 -07:00
index-pack.c index-pack: correct "offset" type in unpack_entry_data() 2016-07-13 09:15:08 -07:00
init-db.c Merge branch 'jk/check-repository-format' into maint 2016-05-02 14:24:04 -07:00
interpret-trailers.c interpret-trailers: add option for in-place editing 2016-01-14 12:22:17 -08:00
log.c Merge branch 'xy/format-patch-base' 2016-05-23 14:54:31 -07:00
ls-files.c Merge branch 'jk/options-cleanup' 2016-02-10 14:20:08 -08:00
ls-remote.c ls-remote: add support for showing symrefs 2016-01-19 10:07:56 -08:00
ls-tree.c convert trivial sprintf / strcpy calls to xsnprintf 2015-09-25 10:18:18 -07:00
mailinfo.c mailinfo: libify 2015-10-21 15:59:34 -07:00
mailsplit.c builtin/mailsplit.c: use error_errno() 2016-05-09 12:29:08 -07:00
merge-base.c convert trivial cases to ALLOC_ARRAY 2016-02-22 14:51:09 -08:00
merge-file.c builtin/merge-file.c: use error_errno() 2016-05-09 12:29:08 -07:00
merge-index.c use sha1_to_hex_r() instead of strcpy 2015-10-05 11:08:05 -07:00
merge-ours.c
merge-recursive.c convert trivial sprintf / strcpy calls to xsnprintf 2015-09-25 10:18:18 -07:00
merge-tree.c struct name_entry: use struct object_id instead of unsigned char sha1[20] 2016-04-25 14:23:42 -07:00
merge.c merge: use string_list_split() in add_strategies() 2016-08-05 15:11:06 -07:00
mktag.c usage: do not insist that standard input must come from a file 2015-10-16 15:27:52 -07:00
mktree.c Merge branch 'jk/tighten-alloc' 2016-02-26 13:37:16 -08:00
mv.c git mv: do not keep slash in git mv dir non-existing-dir/ 2016-08-08 10:43:20 -07:00
name-rev.c Merge branch 'js/name-rev-use-oldest-ref' into maint 2016-05-31 14:08:26 -07:00
notes.c Merge branch 'sb/misc-cleanups' into HEAD 2016-05-18 14:40:15 -07:00
pack-objects.c Merge branch 'nd/pack-ofs-4gb-limit' into maint 2016-08-08 14:21:36 -07:00
pack-redundant.c convert trivial cases to ALLOC_ARRAY 2016-02-22 14:51:09 -08:00
pack-refs.c
patch-id.c Merge branch 'rs/patch-id-use-skip-prefix' 2016-06-03 14:38:03 -07:00
prune-packed.c
prune.c Merge branch 'jk/repository-extension' into maint 2015-11-03 15:32:25 -08:00
pull.c Merge branch 'va/i18n-misc-updates' 2016-05-17 14:38:23 -07:00
push.c Merge branch 'mm/push-default-warning' 2016-02-26 13:37:25 -08:00
read-tree.c convert trivial sprintf / strcpy calls to xsnprintf 2015-09-25 10:18:18 -07:00
receive-pack.c Merge branch 'jk/tighten-alloc' into maint 2016-09-08 21:36:00 -07:00
reflog.c struct name_entry: use struct object_id instead of unsigned char sha1[20] 2016-04-25 14:23:42 -07:00
remote-ext.c typofix: assorted typofixes in comments, documentation and messages 2016-05-06 13:16:37 -07:00
remote-fd.c
remote.c i18n: remote: add comment for translators 2016-05-09 12:20:40 -07:00
repack.c strbuf: introduce strbuf_getline_{lf,nul}() 2016-01-15 10:12:51 -08:00
replace.c Merge branch 'js/replace-edit-use-editor-configuration' into maint 2016-05-06 14:53:24 -07:00
rerere.c Sync with 2.6.1 2015-10-05 13:20:08 -07:00
reset.c Merge branch 'js/find-commit-subject-ignore-leading-blanks' into maint 2016-07-28 11:25:50 -07:00
rev-list.c Merge branch 'jk/rev-list-count-with-bitmap' into maint 2016-06-27 09:56:24 -07:00
rev-parse.c use strbuf_addstr() for adding constant strings to a strbuf 2016-08-01 13:42:10 -07:00
revert.c parse_options: allocate a new array when concatenating 2016-07-06 10:11:08 -07:00
rm.c Merge branch 'rs/rm-strbuf-optim' into maint 2016-08-10 11:55:24 -07:00
send-pack.c Merge branch 'sk/send-pack-all-fix' into maint 2016-04-29 14:15:57 -07:00
shortlog.c Merge branch 'jk/shortlog' 2016-01-28 16:10:14 -08:00
show-branch.c Merge branch 'rs/show-branch-argv-array' into maint 2015-12-11 11:14:14 -08:00
show-ref.c show-ref: stop using PARSE_OPT_NO_INTERNAL_HELP 2015-11-20 08:02:07 -05:00
stripspace.c stripspace: call U+0020 a "space" instead of a "blank" 2016-01-29 16:02:34 -08:00
submodule--helper.c submodule: remove bashism from shell script 2016-06-01 11:32:53 -07:00
symbolic-ref.c symbolic-ref: propagate error code from create_symref() 2015-12-21 12:03:03 -08:00
tag.c Merge branch 'st/verify-tag' 2016-04-29 12:59:09 -07:00
unpack-file.c convert trivial sprintf / strcpy calls to xsnprintf 2015-09-25 10:18:18 -07:00
unpack-objects.c Remove get_object_hash. 2015-11-20 08:02:05 -05:00
update-index.c builtin/update-index.c: prefer "err" to "errno" in process_lstat_error 2016-05-09 12:29:08 -07:00
update-ref.c
update-server-info.c
upload-archive.c builtin/upload-archive.c: use error_errno() 2016-05-09 12:29:08 -07:00
var.c
verify-commit.c
verify-pack.c
verify-tag.c verify-tag: move tag verification code to tag.c 2016-04-22 14:06:46 -07:00
worktree.c Merge branch 'nd/worktree-various-heads' 2016-05-23 14:54:29 -07:00
write-tree.c