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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



+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 <davidbarr@xxxxxxxxxx> wrote:
> 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 <mfick@xxxxxxxxxxxxxx>
> Inspired-by: Julian Phillips <julian@xxxxxxxxxxxxxxxxx>
> Acked-by: Martin Fick <mfick@xxxxxxxxxxxxxx>
> Signed-off-by: David Barr <davidbarr@xxxxxxxxxx>
> ---
>  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@xxxxxxxxxx | 614-3438-8348
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]