The commit slab commit_rev_name contains a pointer to a struct rev_name, and the actual struct is allocated separatly. Avoid that allocation and pointer indirection by storing the full struct in the commit slab. Use the tip_name member pointer to determine if the returned struct is initialized. Performance in the Linux repository measured with hyperfine before: Benchmark #1: ./git -C ../linux/ name-rev --all Time (mean ± σ): 953.5 ms ± 6.3 ms [User: 901.2 ms, System: 52.1 ms] Range (min … max): 945.2 ms … 968.5 ms 10 runs ... and with this patch: Benchmark #1: ./git -C ../linux/ name-rev --all Time (mean ± σ): 851.0 ms ± 3.1 ms [User: 807.4 ms, System: 43.6 ms] Range (min … max): 846.7 ms … 857.0 ms 10 runs Signed-off-by: René Scharfe <l.s.r@xxxxxx> --- builtin/name-rev.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 41aed436ca..14381a3c64 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -24,7 +24,7 @@ struct rev_name { int from_tag; }; -define_commit_slab(commit_rev_name, struct rev_name *); +define_commit_slab(commit_rev_name, struct rev_name); static timestamp_t cutoff = TIME_MAX; static struct commit_rev_name rev_names; @@ -32,11 +32,16 @@ static struct commit_rev_name rev_names; /* How many generations are maximally preferred over _one_ merge traversal? */ #define MERGE_TRAVERSAL_WEIGHT 65535 +static int is_valid_rev_name(const struct rev_name *name) +{ + return name && name->tip_name; +} + static struct rev_name *get_commit_rev_name(const struct commit *commit) { - struct rev_name **slot = commit_rev_name_peek(&rev_names, commit); + struct rev_name *name = commit_rev_name_peek(&rev_names, commit); - return slot ? *slot : NULL; + return is_valid_rev_name(name) ? name : NULL; } static int is_better_name(struct rev_name *name, @@ -81,15 +86,12 @@ static struct rev_name *create_or_update_name(struct commit *commit, int generation, int distance, int from_tag) { - struct rev_name **slot = commit_rev_name_at(&rev_names, commit); - struct rev_name *name = *slot; + struct rev_name *name = commit_rev_name_at(&rev_names, commit); - if (name && !is_better_name(name, taggerdate, distance, from_tag)) + if (is_valid_rev_name(name) && + !is_better_name(name, taggerdate, distance, from_tag)) return NULL; - if (!name) - name = *slot = xmalloc(sizeof(*name)); - name->tip_name = tip_name; name->taggerdate = taggerdate; name->generation = generation; -- 2.25.0