Fix "git commit directory/" performance anomaly
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Aug 2007 16:51:58 +0000 (09:51 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 10 Aug 2007 20:57:43 +0000 (13:57 -0700)
This trivial patch avoids re-hashing files that are already clean in the
index. This mirrors what commit 0781b8a9b2fe760fc4ed519a3a26e4b9bd6ccffe
did for "git add .", only for "git commit ." instead.

This improves the cold-cache case immensely, since we don't need to bring
in all the file contents, just the index and any files dirty in the index.

Before:

[torvalds@woody linux]$ time git commit .
real    1m49.537s
user    0m3.892s
sys     0m2.432s

After:

[torvalds@woody linux]$ time git commit .
real    0m14.273s
user    0m1.312s
sys     0m0.516s

(both after doing a "echo 3 > /proc/sys/vm/drop_caches" to get cold-cache
behaviour - even with the index optimization git still has to "lstat()"
all the files, so with a truly cold cache, bringing all the inodes in
will take some time).

[jc: trivial "return 0;" fixed]

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-update-index.c

index 509369e9e7b1719e53ba2dd2d976066fb9513353..a7a4574f2bff2a7db4a1c25aa4a514ad99760381 100644 (file)
@@ -86,9 +86,15 @@ static int process_lstat_error(const char *path, int err)
 
 static int add_one_path(struct cache_entry *old, const char *path, int len, struct stat *st)
 {
-       int option, size = cache_entry_size(len);
-       struct cache_entry *ce = xcalloc(1, size);
+       int option, size;
+       struct cache_entry *ce;
+
+       /* Was the old index entry already up-to-date? */
+       if (old && !ce_stage(old) && !ce_match_stat(old, st, 0))
+               return 0;
 
+       size = cache_entry_size(len);
+       ce = xcalloc(1, size);
        memcpy(ce->name, path, len);
        ce->ce_flags = htons(len);
        fill_stat_cache_info(ce, st);