Make git_dir a path relative to work_tree in setup_work_tree()
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Jun 2008 19:34:06 +0000 (12:34 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 19 Jun 2008 23:44:21 +0000 (16:44 -0700)
Once we find the absolute paths for git_dir and work_tree, we can make
git_dir a relative path since we know pwd will be work_tree. This should
save the kernel some time traversing the path to work_tree all the time
if git_dir is inside work_tree.

Daniel's patch didn't apply for me as-is, so I recreated it with some
differences, and here are the numbers from ten runs each.

There is some IO for me - probably due to more-or-less random flushing of
the journal - so the variation is bigger than I'd like, but whatever:

Before:
real    0m8.135s
real    0m7.933s
real    0m8.080s
real    0m7.954s
real    0m7.949s
real    0m8.112s
real    0m7.934s
real    0m8.059s
real    0m7.979s
real    0m8.038s

After:
real    0m7.685s
real    0m7.968s
real    0m7.703s
real    0m7.850s
real    0m7.995s
real    0m7.817s
real    0m7.963s
real    0m7.955s
real    0m7.848s
real    0m7.969s

Now, going by "best of ten" (on the assumption that the longer numbers
are all due to IO), I'm saying a 7.933s -> 7.685s reduction, and it does
seem to be outside of the noise (ie the "after" case never broke 8s, while
the "before" case did so half the time).

So looks like about 3% to me.

Doing it for a slightly smaller test-case (just the "arch" subdirectory)
gets more stable numbers probably due to not filling the journal with
metadata updates, so we have:

Before:
real    0m1.633s
real    0m1.633s
real    0m1.633s
real    0m1.632s
real    0m1.632s
real    0m1.630s
real    0m1.634s
real    0m1.631s
real    0m1.632s
real    0m1.632s

After:
real    0m1.610s
real    0m1.609s
real    0m1.610s
real    0m1.608s
real    0m1.607s
real    0m1.610s
real    0m1.609s
real    0m1.611s
real    0m1.608s
real    0m1.611s

where I'ld just take the averages and say 1.632 vs 1.610, which is just
over 1% peformance improvement.

So it's not in the noise, but it's not as big as I initially thought and
measured.

(That said, it obviously depends on how deep the working directory path is
too, and whether it is behind NFS or something else that might need to
cause more work to look up).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
path.c
setup.c

diff --git a/cache.h b/cache.h
index 81b7e17de26ae33249c60b101f5718cb5c5e5699..56ac6e7f4702d0c1665c73e8fc44cfc047bcfd33 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -525,6 +525,7 @@ static inline int is_absolute_path(const char *path)
 }
 const char *make_absolute_path(const char *path);
 const char *make_nonrelative_path(const char *path);
+const char *make_relative_path(const char *abs, const char *base);
 
 /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
 extern int sha1_object_info(const unsigned char *, unsigned long *);
diff --git a/path.c b/path.c
index 7a35a26a1697480f0f43244132d8267deb301651..6e3df1849965be6a88fac89c007f9b5fe960f825 100644 (file)
--- a/path.c
+++ b/path.c
@@ -330,6 +330,23 @@ const char *make_nonrelative_path(const char *path)
 /* We allow "recursive" symbolic links. Only within reason, though. */
 #define MAXDEPTH 5
 
+const char *make_relative_path(const char *abs, const char *base)
+{
+       static char buf[PATH_MAX + 1];
+       int baselen;
+       if (!base)
+               return abs;
+       baselen = strlen(base);
+       if (prefixcmp(abs, base))
+               return abs;
+       if (abs[baselen] == '/')
+               baselen++;
+       else if (base[baselen - 1] != '/')
+               return abs;
+       strcpy(buf, abs + baselen);
+       return buf;
+}
+
 const char *make_absolute_path(const char *path)
 {
        static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
diff --git a/setup.c b/setup.c
index d630e374e7c03b934de14adceb93c9c327796e6d..3b111ea7cf5f68ecca085f5a56421ea190e1771a 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -292,9 +292,10 @@ void setup_work_tree(void)
        work_tree = get_git_work_tree();
        git_dir = get_git_dir();
        if (!is_absolute_path(git_dir))
-               set_git_dir(make_absolute_path(git_dir));
+               git_dir = make_absolute_path(git_dir);
        if (!work_tree || chdir(work_tree))
                die("This operation must be run in a work tree");
+       set_git_dir(make_relative_path(git_dir, work_tree));
        initialized = 1;
 }