aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2015-06-09 13:24:37 -0400
committerJunio C Hamano <gitster@pobox.com>2015-06-09 12:26:35 -0700
commit0eeb077be7d526635995e17808927c94c70be665 (patch)
treeaa0c85228872134e3497235bc1a86009a6f20dcc
parent282616c72d1d08a77ca4fe1186cb708c38408d87 (diff)
downloadgit-0eeb077be7d526635995e17808927c94c70be665.tar.gz
git-0eeb077be7d526635995e17808927c94c70be665.tar.xz
index-pack: avoid excessive re-reading of pack directory
Since 45e8a74 (has_sha1_file: re-check pack directory before giving up, 2013-08-30), we spend extra effort for has_sha1_file to give the right answer when somebody else is repacking. Usually this effort does not matter, because after finding that the object does not exist, the next step is usually to die(). However, some code paths make a large number of has_sha1_file checks which are _not_ expected to return 1. The collision test in index-pack.c is such a case. On a local system, this can cause a performance slowdown of around 5%. But on a system with high-latency system calls (like NFS), it can be much worse. This patch introduces a "quick" flag to has_sha1_file which callers can use when they would prefer high performance at the cost of false negatives during repacks. There may be other code paths that can use this, but the index-pack one is the most obviously critical, so we'll start with switching that one. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/index-pack.c2
-rw-r--r--cache.h11
-rw-r--r--sha1_file.c4
3 files changed, 14 insertions, 3 deletions
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 9ca020392..96b110445 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -721,7 +721,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
assert(data || obj_entry);
read_lock();
- collision_test_needed = has_sha1_file(sha1);
+ collision_test_needed = has_sha1_file_with_flags(sha1, HAS_SHA1_QUICK);
read_unlock();
if (collision_test_needed && !data) {
diff --git a/cache.h b/cache.h
index f23fdbee9..3fb757067 100644
--- a/cache.h
+++ b/cache.h
@@ -873,8 +873,17 @@ extern int has_sha1_pack(const unsigned char *sha1);
* Return true iff we have an object named sha1, whether local or in
* an alternate object database, and whether packed or loose. This
* function does not respect replace references.
+ *
+ * If the QUICK flag is set, do not re-check the pack directory
+ * when we cannot find the object (this means we may give a false
+ * negative answer if another process is simultaneously repacking).
*/
-extern int has_sha1_file(const unsigned char *sha1);
+#define HAS_SHA1_QUICK 0x1
+extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags);
+static inline int has_sha1_file(const unsigned char *sha1)
+{
+ return has_sha1_file_with_flags(sha1, 0);
+}
/*
* Return true iff an alternate object database has a loose object
diff --git a/sha1_file.c b/sha1_file.c
index a38854ce5..18d0bfb8a 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -3017,7 +3017,7 @@ int has_sha1_pack(const unsigned char *sha1)
return find_pack_entry(sha1, &e);
}
-int has_sha1_file(const unsigned char *sha1)
+int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
{
struct pack_entry e;
@@ -3025,6 +3025,8 @@ int has_sha1_file(const unsigned char *sha1)
return 1;
if (has_loose_object(sha1))
return 1;
+ if (flags & HAS_SHA1_QUICK)
+ return 0;
reprepare_packed_git();
return find_pack_entry(sha1, &e);
}