Code

Why is "git tag --contains" so slow?
authorJeff King <peff@peff.net>
Mon, 5 Jul 2010 12:39:23 +0000 (08:39 -0400)
committerJunio C Hamano <gitster@pobox.com>
Mon, 5 Jul 2010 19:15:11 +0000 (12:15 -0700)
On Mon, Jul 05, 2010 at 08:27:23AM -0400, Jeff King wrote:

> As you probably guessed from the specificity of the number, I wrote a
> short program to actually traverse and find the worst skew. It takes
> about 5 seconds to run (unsurprisingly, since it is doing the same full
> traversal that we end up doing in the above numbers). So we could
> "autoskew" by setting up the configuration on clone, and then
> periodically updating it as part of "git gc".

This patch doesn't implement auto-detection of skew, but is the program
I used to calculate, and would provide the basis for such
auto-detection. It would be interesting to see average skew numbers for
popular repositories. You can run it as "git skew --all".

Signed-off-by: Junio C Hamano <gitster@pobox.com>
.gitignore
Makefile
builtin.h
builtin/skew.c [new file with mode: 0644]
git.c
t/README

index 14e2b6bde9bef55d678da8ba44dc180b039cd3ac..90aff178605a2a060c27e2181fdfdbf22c30823b 100644 (file)
 /git-show-branch
 /git-show-index
 /git-show-ref
+/git-skew
 /git-stage
 /git-stash
 /git-status
index 9aca8a16d955e904b4a8f07e70fba754ac65fcc3..e673bdf60326b3f82723ce672abb00c0c741bcb5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -725,6 +725,7 @@ BUILTIN_OBJS += builtin/send-pack.o
 BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
+BUILTIN_OBJS += builtin/skew.o
 BUILTIN_OBJS += builtin/stripspace.o
 BUILTIN_OBJS += builtin/symbolic-ref.o
 BUILTIN_OBJS += builtin/tag.o
index ed6ee26933430e1db4e29e62badfaf0b217935ad..5f5dc0abb8eeb5d1d429924623c480080ae61ca1 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -141,5 +141,6 @@ extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
 extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_pack_refs(int argc, const char **argv, const char *prefix);
 extern int cmd_replace(int argc, const char **argv, const char *prefix);
+extern int cmd_skew(int argc, const char **argv, const char *prefix);
 
 #endif
diff --git a/builtin/skew.c b/builtin/skew.c
new file mode 100644 (file)
index 0000000..1046f5f
--- /dev/null
@@ -0,0 +1,50 @@
+#include "cache.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
+
+unsigned long worst_skew = 0;
+
+static void check_skew_recurse(struct commit *c, unsigned long when)
+{
+       struct commit_list *p;
+
+       if (c->object.flags & SEEN)
+               return;
+       c->object.flags |= SEEN;
+
+       if (parse_commit(c) < 0)
+               return;
+
+       if (c->date > when) {
+               unsigned long skew = c->date - when;
+               if (skew > worst_skew)
+                       worst_skew = skew;
+       }
+
+       for (p = c->parents; p; p = p->next)
+               check_skew_recurse(p->item, c->date < when ? c->date : when);
+}
+
+static void check_skew(struct commit *c)
+{
+       check_skew_recurse(c, time(NULL));
+}
+
+int cmd_skew(int argc, const char **argv, const char *prefix) {
+       struct rev_info revs;
+       int i;
+
+       git_config(git_default_config, NULL);
+       init_revisions(&revs, prefix);
+       argc = setup_revisions(argc, argv, &revs, NULL);
+
+       for (i = 0; i < revs.pending.nr; i++) {
+               struct object *o = revs.pending.objects[i].item;
+               if (o->type == OBJ_COMMIT)
+                       check_skew((struct commit *)o);
+       }
+
+       printf("%lu\n", worst_skew);
+       return 0;
+}
diff --git a/git.c b/git.c
index 265fa09d8d361ec0dab3626c846906f100cd6949..8a77fe314c9ed2cec7d05430750d088f8ed48442 100644 (file)
--- a/git.c
+++ b/git.c
@@ -399,6 +399,7 @@ static void handle_internal_command(int argc, const char **argv)
                { "verify-pack", cmd_verify_pack },
                { "show-ref", cmd_show_ref, RUN_SETUP },
                { "pack-refs", cmd_pack_refs, RUN_SETUP },
+               { "skew", cmd_skew, RUN_SETUP },
        };
        int i;
        static const char ext[] = STRIP_EXTENSION;
index 0e4e8d8862c96383a6f6f22a1b6bb01044925620..691938c906aa9762d31ff70a0920be8f3600a097 100644 (file)
--- a/t/README
+++ b/t/README
@@ -198,9 +198,10 @@ This test harness library does the following things:
  - If the script is invoked with command line argument --help
    (or -h), it shows the test_description and exits.
 
- - Creates an empty test directory with an empty .git/objects
-   database and chdir(2) into it.  This directory is 't/trash directory'
-   if you must know, but I do not think you care.
+ - Creates an empty test directory with an empty .git/objects database
+   and chdir(2) into it.  This directory is 't/trash
+   directory.$test_name_without_dotsh', with t/ subject to change by
+   the --root option documented above.
 
  - Defines standard test helper functions for your scripts to
    use.  These functions are designed to make all scripts behave