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

[PATCH 1/3] ref-filter: avoid parsing tagged objects in match_points_at()

From
Jeff King <peff@peff.net>
Date
Jul 2, 2023, 22:35 UTC
Message-ID
<20230702223540.GA3494279@coredump.intra.peff.net>
In-Reply-To
<20230702223342.GA1598765@coredump.intra.peff.net>

When we peel tags to check if they match a --points-at oid, we recursively parse the tagged object to see if it is also a tag. But since the tag itself tells us the type of the object it points to (and even gives us the appropriate object struct via its "tagged" member), we can use that directly.

We do still have to make sure to call parse_tag() before looking at each tag. This is redundant for the outermost tag (since we did call parse_object() to find its type), but that's OK; parse_tag() is smart enough to make this a noop when the tag has already been parsed.

In my clone of linux.git, with 782 tags (and only 3 non-tags), this yields a significant speedup (bringing us back where we were before the commit before this one started recursively dereferencing tags):

  Benchmark 1: ./git.old for-each-ref --points-at=HEAD --format="%(refname)"
    Time (mean ± σ):      20.3 ms ±   0.5 ms    [User: 11.1 ms, System: 9.1 ms]
    Range (min … max):    19.6 ms …  21.5 ms    141 runs
  Benchmark 2: ./git.new for-each-ref --points-at=HEAD --format="%(refname)"
    Time (mean ± σ):      11.4 ms ±   0.2 ms    [User: 6.3 ms, System: 5.0 ms]
    Range (min … max):    11.0 ms …  12.2 ms    250 runs
  Summary
    './git.new for-each-ref --points-at=HEAD --format="%(refname)"' ran
      1.79 ± 0.05 times faster than './git.old for-each-ref --points-at=HEAD --format="%(refname)"'
Signed-off-by: Jeff King <peff@peff.net>
---
This could optionally be squashed into the original. If we leave it as
its own patch, it might be worth replacing "the commit before this one"
with the actual oid (once Junio has picked it up and it's stable).
 ref-filter.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index ad7f244414..e091f056ab 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2225,10 +2225,18 @@ static const struct object_id *match_points_at(struct oid_array *points_at,
 		return oid;
 	obj = parse_object(the_repository, oid);
 	while (obj && obj->type == OBJ_TAG) {
-		oid = get_tagged_oid((struct tag *)obj);
+		struct tag *tag = (struct tag *)obj;
+
+		if (parse_tag(tag) < 0) {
+			obj = NULL;
+			break;
+		}
+
+		oid = get_tagged_oid(tag);
 		if (oid_array_lookup(points_at, oid) >= 0)
 			return oid;
-		obj = parse_object(the_repository, oid);
+
+		obj = tag->tagged;
 	}
 	if (!obj)
 		die(_("malformed object at '%s'"), refname);
-- 
2.41.0.586.g3c0cc15bc7
Previous: Jeff KingNext: Jeff King
Message 7 of 15 in “ref-filter: handle nested tags in --points-at option”
  1. ref-filter: handle nested tags in --points-at optionJan Klötzke, Jul 1, 2023
  2. Jeff KingJul 2, 2023
  3. René ScharfeJul 2, 2023
  4. Jeff KingJul 2, 2023
  5. Jeff KingJul 2, 2023
  6. 0/3 a few --points-at optimizations/cleanupsJeff King, Jul 2, 2023
  7. 1/3 ref-filter: avoid parsing tagged objects in match_points_at()Jeff King, Jul 2, 2023
  8. 2/3 ref-filter: avoid parsing non-tags in match_points_at()Jeff King, Jul 2, 2023
  9. 3/3 ref-filter: simplify return type of match_points_atJeff King, Jul 2, 2023
  10. Jan KlötzkeJul 3, 2023
  11. Junio C HamanoJul 5, 2023
  12. Jeff KingJul 5, 2023
  13. Junio C HamanoJul 5, 2023
  14. Jan KlötzkeJul 5, 2023
  15. Junio C HamanoJul 5, 2023

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.