Thread (70 messages) flat view 70 messages, 15 authors, 2016-06-15

Re: [PATCH] refs.c: Fix slowness with numerous loose refs

From: David Michael Barr <hidden>
Date: 2016-06-15 22:52:07

+cc Shawn O. Pearce

I used the following to generate a test repo shaped like
a gerrit mirror with unpacked refs (10k, because life is too short for
100k tests):

cd test.git
git init
touch empty
git add empty
git commit -m 'empty'
REV=`git rev-parse HEAD`
for ((d=0;d<100;++d)); do
 for ((n=0;n<100;++n)); do
  let r=n*100+d
  mkdir -p .git/refs/changes/$d/$r
  echo $REV > .git/refs/changes/$d/$r/1
 done
done
time git branch xyz

With warm caches...

Git 1.7.6.4:
real	0m8.232s
user	0m7.842s
sys	0m0.385s

Git 1.7.6.4, with patch below:
real	0m0.394s
user	0m0.069s
sys	0m0.324s

On Tue, Sep 27, 2011 at 11:01 AM, David Barr [off-list ref] wrote:
quoted hunk ↗ jump to hunk
Martin Fick reported:
 OK, I have found what I believe is another performance
 regression for large ref counts (~100K).

 When I run git br on my repo which only has one branch, but
 has ~100K refs under ref/changes (a gerrit repo), it takes
 normally 3-6mins depending on whether my caches are fresh or
 not.  After bisecting some older changes, I noticed that
 this ref seems to be where things start to get slow:
 v1.5.2-rc0~21^2 (refs.c: add a function to sort a ref list,
 rather then sorting on add) (Julian Phillips, Apr 17, 2007)

Martin Fick observed that sort_refs_lists() was called almost
as many times as there were loose refs.

Julian Phillips commented:
 Back when I made that change, I failed to notice that get_ref_dir
 was recursive for subdirectories ... sorry ...

 Hopefully this should speed things up. My test repo went from
 ~17m user time, to ~2.5s.
 Packing still make things much faster of course.

Martin Fick acked:
 Excellent!  This works (almost, in my refs.c it is called
 sort_ref_list, not sort_refs_list).  So, on the non garbage
 collected repo, git branch now takes ~.5s, and in the
 garbage collected one it takes only ~.05s!

[db: summarised transcript, rewrote patch to fix callee not callers]

[attn jch: patch applies to maint]

Analyzed-by: Martin Fick [off-list ref]
Inspired-by: Julian Phillips [off-list ref]
Acked-by: Martin Fick <redacted>
Signed-off-by: David Barr <redacted>
---
 refs.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/refs.c b/refs.c
index 4c1fd47..e40a09c 100644
--- a/refs.c
+++ b/refs.c
@@ -255,8 +255,8 @@ static struct ref_list *get_packed_refs(const char *submodule)
       return refs->packed;
 }

-static struct ref_list *get_ref_dir(const char *submodule, const char *base,
-                                   struct ref_list *list)
+static struct ref_list *walk_ref_dir(const char *submodule, const char *base,
+                                    struct ref_list *list)
 {
       DIR *dir;
       const char *path;
@@ -299,7 +299,7 @@ static struct ref_list *get_ref_dir(const char *submodule, const char *base,
                       if (stat(refdir, &st) < 0)
                               continue;
                       if (S_ISDIR(st.st_mode)) {
-                               list = get_ref_dir(submodule, ref, list);
+                               list = walk_ref_dir(submodule, ref, list);
                               continue;
                       }
                       if (submodule) {
@@ -319,7 +319,13 @@ static struct ref_list *get_ref_dir(const char *submodule, const char *base,
               free(ref);
               closedir(dir);
       }
-       return sort_ref_list(list);
+       return list;
+}
+
+static struct ref_list *get_ref_dir(const char *submodule, const char *base,
+                                   struct ref_list *list)
+{
+       return sort_ref_list(walk_ref_dir(submodule, base, list));
 }

 struct warn_if_dangling_data {
--
1.7.5.75.g69330


-- 

David Barr | Software Engineer | davidbarr@google.com | 614-3438-8348
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help