summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@osdl.org>2005-09-16 14:55:33 -0700
committerJunio C Hamano <junkio@cox.net>2005-09-16 15:32:23 -0700
commit8805ccac40348094d26b3b892c6ca3d08dc12ae0 (patch)
treeb4465f53abbb399d7491f5b0060d9b5076f52794
parentb0d8923ec01fd91b75ab079034f89ced91500157 (diff)
downloadgit-8805ccac40348094d26b3b892c6ca3d08dc12ae0.tar.gz
[PATCH] Avoid building object ref lists when not needed
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>
-rw-r--r--object.c13
-rw-r--r--object.h1
-rw-r--r--rev-list.c1
3 files changed, 12 insertions, 3 deletions
diff --git a/object.c b/object.c
index 63e6e784d4..1fdebe012b 100644
--- 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;
diff --git a/object.h b/object.h
index bf744490a9..6accda33d8 100644
--- 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;
diff --git a/rev-list.c b/rev-list.c
index 91534dd239..c55e912be4 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -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);