git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Avoid building object ref lists when not needed

From
Linus Torvalds <torvalds@osdl.org>
Date
Sep 16, 2005, 21:55 UTC
Message-ID
<Pine.LNX.4.58.0509161446100.26803@g5.osdl.org>

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:
	[torvalds@g5 linux]$ /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:
	[torvalds@g5 linux]$ /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>
----
diff --git a/object.c b/object.c
--- 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 
 
 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, 
 {
 	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
--- 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
--- 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);
Next: Linus Torvalds
Message 1 of 3 in “Avoid building object ref lists when not needed”
  1. Linus TorvaldsSep 16, 2005
  2. Linus TorvaldsSep 16, 2005
  3. Junio C HamanoSep 16, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.