Skip to content

Commit 9b21a34

Browse files
peffgitster
authored andcommitted
shortlog: optimize out useless string list
If we are in "--summary" mode, then we do not care about the actual list of subject onelines associated with each author. We care only about the number. So rather than store a string-list for each author full of "<none>", let's just keep a count. This drops my best-of-five for "git shortlog -ns HEAD" on linux.git from: real 0m5.194s user 0m5.028s sys 0m0.168s to: real 0m5.057s user 0m4.916s sys 0m0.144s That's about 2.5%. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ed7eba9 commit 9b21a34

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

builtin/shortlog.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,26 @@ static char const * const shortlog_usage[] = {
1414
NULL
1515
};
1616

17-
static int compare_by_number(const void *a1, const void *a2)
17+
/*
18+
* The util field of our string_list_items will contain one of two things:
19+
*
20+
* - if --summary is not in use, it will point to a string list of the
21+
* oneline subjects assigned to this author
22+
*
23+
* - if --summary is in use, we don't need that list; we only need to know
24+
* its size. So we abuse the pointer slot to store our integer counter.
25+
*
26+
* This macro accesses the latter.
27+
*/
28+
#define UTIL_TO_INT(x) ((intptr_t)(x)->util)
29+
30+
static int compare_by_counter(const void *a1, const void *a2)
31+
{
32+
const struct string_list_item *i1 = a1, *i2 = a2;
33+
return UTIL_TO_INT(i2) - UTIL_TO_INT(i1);
34+
}
35+
36+
static int compare_by_list(const void *a1, const void *a2)
1837
{
1938
const struct string_list_item *i1 = a1, *i2 = a2;
2039
const struct string_list *l1 = i1->util, *l2 = i2->util;
@@ -52,11 +71,9 @@ static void insert_one_record(struct shortlog *log,
5271
strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
5372

5473
item = string_list_insert(&log->list, namemailbuf.buf);
55-
if (item->util == NULL)
56-
item->util = xcalloc(1, sizeof(struct string_list));
5774

5875
if (log->summary)
59-
string_list_append(item->util, xstrdup(""));
76+
item->util = (void *)(UTIL_TO_INT(item) + 1);
6077
else {
6178
const char *dot3 = log->common_repo_prefix;
6279
char *buffer, *p;
@@ -90,6 +107,8 @@ static void insert_one_record(struct shortlog *log,
90107
}
91108
}
92109

110+
if (item->util == NULL)
111+
item->util = xcalloc(1, sizeof(struct string_list));
93112
string_list_append(item->util, buffer);
94113
}
95114
}
@@ -295,14 +314,14 @@ void shortlog_output(struct shortlog *log)
295314

296315
if (log->sort_by_number)
297316
qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
298-
compare_by_number);
317+
log->summary ? compare_by_counter : compare_by_list);
299318
for (i = 0; i < log->list.nr; i++) {
300-
struct string_list *onelines = log->list.items[i].util;
301-
319+
const struct string_list_item *item = &log->list.items[i];
302320
if (log->summary) {
303-
printf("%6d\t%s\n", onelines->nr, log->list.items[i].string);
321+
printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string);
304322
} else {
305-
printf("%s (%d):\n", log->list.items[i].string, onelines->nr);
323+
struct string_list *onelines = item->util;
324+
printf("%s (%d):\n", item->string, onelines->nr);
306325
for (j = onelines->nr - 1; j >= 0; j--) {
307326
const char *msg = onelines->items[j].string;
308327

@@ -315,11 +334,11 @@ void shortlog_output(struct shortlog *log)
315334
printf(" %s\n", msg);
316335
}
317336
putchar('\n');
337+
onelines->strdup_strings = 1;
338+
string_list_clear(onelines, 0);
339+
free(onelines);
318340
}
319341

320-
onelines->strdup_strings = 1;
321-
string_list_clear(onelines, 0);
322-
free(onelines);
323342
log->list.items[i].util = NULL;
324343
}
325344

0 commit comments

Comments
 (0)