[PATCH] Avoid building object ref lists when not needed
authorLinus Torvalds <torvalds@osdl.org>
Fri, 16 Sep 2005 21:55:33 +0000 (14:55 -0700)
committerJunio C Hamano <junkio@cox.net>
Fri, 16 Sep 2005 22:32:23 +0000 (15:32 -0700)
The object parsing code builds a generic "this object references that
object" because doing a full connectivity check for fsck requires it.

However, nothing else really needs it, and it's quite expensive for
git-rev-list that can have tons of objects in flight.

So, exactly like the commit buffer save thing, add a global flag to
disable it, and use it in git-rev-list.

Before:

$ /usr/bin/time git-rev-list --objects v2.6.12..HEAD | wc -l
12.28user 0.29system 0:12.57elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+26718minor)pagefaults 0swaps
59124

After this change:

$ /usr/bin/time git-rev-list --objects v2.6.12..HEAD | wc -l
10.33user 0.18system 0:10.54elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+18509minor)pagefaults 0swaps
59124

and note how the number of pages touched by git-rev-list for this
particular object list has shrunk from 26,718 (104 MB) to 18,509 (72 MB).

Calculating the total object difference between two git revisions is still
clearly the most expensive git operation (both in memory and CPU time),
but it's now less than 40% of what it used to be.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
object.c
object.h
rev-list.c

index 63e6e784d41ef5aa7bb387a96a85bf0f8e7248ab..1fdebe012ba8a6db0b6eae443e40a7f74ae2d597 100644 (file)
--- a/object.c
+++ b/object.c
@@ -9,6 +9,8 @@ struct object **objs;
 int nr_objs;
 static int obj_allocs;
 
+int track_object_refs = 1;
+
 static int find_object(const unsigned char *sha1)
 {
        int first = 0, last = nr_objs;
@@ -67,9 +69,12 @@ void created_object(const unsigned char *sha1, struct object *obj)
 
 void add_ref(struct object *refer, struct object *target)
 {
-       struct object_list **pp = &refer->refs;
-       struct object_list *p;
-       
+       struct object_list **pp, *p;
+
+       if (!track_object_refs)
+               return;
+
+       pp = &refer->refs;
        while ((p = *pp) != NULL) {
                if (p->item == target)
                        return;
@@ -87,6 +92,8 @@ void mark_reachable(struct object *obj, unsigned int mask)
 {
        struct object_list *p = obj->refs;
 
+       if (!track_object_refs)
+               die("cannot do reachability with object refs turned off");
        /* If we've been here already, don't bother */
        if (obj->flags & mask)
                return;
index bf744490a9a75c5e84af6384b2fa2bc4eb492452..6accda33d8c8d6b8ef33a4df50bf350d9f088dc6 100644 (file)
--- a/object.h
+++ b/object.h
@@ -17,6 +17,7 @@ struct object {
        void *util;
 };
 
+extern int track_object_refs;
 extern int nr_objs;
 extern struct object **objs;
 
index 91534dd239173b5821656b40a6e79b3a4ff66cca..c55e912be4faa81a70c9cc27ef44d72a74d49a41 100644 (file)
@@ -581,6 +581,7 @@ int main(int argc, char **argv)
        }
 
        save_commit_buffer = verbose_header;
+       track_object_refs = 0;
 
        if (!merge_order) {             
                sort_by_date(&list);