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

[PATCH 2/2] upload-pack: avoid parsing tag destinations

From
Jeff King <peff@peff.net>
Date
Jan 6, 2012, 19:18 UTC
Message-ID
<20120106191801.GB12903@sigill.intra.peff.net>
In-Reply-To
<7vipkpn87d.fsf@alter.siamese.dyndns.org>

When upload-pack advertises refs, it dereferences any tags it sees, and shows the resulting sha1 to the client. It does this by calling deref_tag. That function must load and parse each tag object to find the sha1 of the tagged object. However, it also ends up parsing the tagged object itself, which is not strictly necessary for upload-pack's use.

Each tag produces two object loads (assuming it is not a recursive tag), when it could get away with only a single one. Dropping the second load halves the effort we spend.

The downside is that we are no longer verifying the resulting object by loading it. In particular:

  1. We never cross-check the "type" field given in the tag
     object with the type of the pointed-to object.  If the
     tag says it points to a tag but doesn't, then we will
     keep peeling and realize the error.  If the tag says it
     points to a non-tag but actually points to a tag, we
     will stop peeling and just advertise the pointed-to
     tag.
  2. If we are missing the pointed-to object, we will not
     realize (because we never even look it up in the object
     db).

However, both of these are errors in the object database, and both will be detected if a client actually requests the broken objects in question. So we are simply pushing the verification away from the advertising stage, and down to the actual fetching stage.

On my test repo with 120K refs, this drops the time to advertise the refs from ~3.2s to ~2.0s.

Signed-off-by: Jeff King <peff@peff.net>
---
 tag.c         |   12 ++++++++++++
 tag.h         |    1 +
 upload-pack.c |    3 +--
 3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/tag.c b/tag.c
index 3aa186d..78d272b 100644
--- a/tag.c
+++ b/tag.c
@@ -24,6 +24,18 @@ struct object *deref_tag(struct object *o, const char *warn, int warnlen)
 	return o;
 }
 
+struct object *deref_tag_noverify(struct object *o)
+{
+	while (o && o->type == OBJ_TAG) {
+		o = parse_object(o->sha1);
+		if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
+			o = ((struct tag *)o)->tagged;
+		else
+			o = NULL;
+	}
+	return o;
+}
+
 struct tag *lookup_tag(const unsigned char *sha1)
 {
 	struct object *obj = lookup_object(sha1);
diff --git a/tag.h b/tag.h
index 5ee88e6..bc8a1e4 100644
--- a/tag.h
+++ b/tag.h
@@ -16,6 +16,7 @@ extern struct tag *lookup_tag(const unsigned char *sha1);
 extern int parse_tag_buffer(struct tag *item, const void *data, unsigned long size);
 extern int parse_tag(struct tag *item);
 extern struct object *deref_tag(struct object *, const char *, int);
+extern struct object *deref_tag_noverify(struct object *);
 extern size_t parse_signature(const char *buf, unsigned long size);
 
 #endif /* TAG_H */
diff --git a/upload-pack.c b/upload-pack.c
index 65cb0ff..c01e161 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -741,8 +741,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 		nr_our_refs++;
 	}
 	if (o->type == OBJ_TAG) {
-		o = parse_object(o->sha1);
-		o = deref_tag(o, refname, 0);
+		o = deref_tag_noverify(o);
 		if (o)
 			packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname_nons);
 	}
-- 
1.7.6.5.14.g7b06f
Previous: Jeff King
Message 17 of 17 in “parse_object: try internal cache before reading object db”
  1. parse_object: try internal cache before reading object dbJeff King, Jan 5, 2012
  2. Junio C HamanoJan 5, 2012
  3. Jeff KingJan 5, 2012
  4. Junio C HamanoJan 5, 2012
  5. Jeff KingJan 5, 2012
  6. Jeff KingJan 6, 2012
  7. Junio C HamanoJan 6, 2012
  8. Jeff KingJan 6, 2012
  9. Junio C HamanoJan 6, 2012
  10. Jeff KingJan 6, 2012
  11. 1/2 upload-pack: avoid parsing objects during ref advertisementJeff King, Jan 6, 2012
  12. Junio C HamanoJan 18, 2013
  13. Jeff KingJan 24, 2013
  14. Junio C HamanoJan 24, 2013
  15. Shawn PearceJan 29, 2013
  16. Jeff KingJan 29, 2013
  17. 2/2 upload-pack: avoid parsing tag destinationsJeff King, Jan 6, 2012

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.