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 <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2016-01-18 15:02:59 -05:00 committed by Junio C Hamano
parent ed7eba9022
commit 9b21a34a96

View file

@ -14,7 +14,26 @@ static char const * const shortlog_usage[] = {
NULL
};
static int compare_by_number(const void *a1, const void *a2)
/*
* The util field of our string_list_items will contain one of two things:
*
* - if --summary is not in use, it will point to a string list of the
* oneline subjects assigned to this author
*
* - if --summary is in use, we don't need that list; we only need to know
* its size. So we abuse the pointer slot to store our integer counter.
*
* This macro accesses the latter.
*/
#define UTIL_TO_INT(x) ((intptr_t)(x)->util)
static int compare_by_counter(const void *a1, const void *a2)
{
const struct string_list_item *i1 = a1, *i2 = a2;
return UTIL_TO_INT(i2) - UTIL_TO_INT(i1);
}
static int compare_by_list(const void *a1, const void *a2)
{
const struct string_list_item *i1 = a1, *i2 = a2;
const struct string_list *l1 = i1->util, *l2 = i2->util;
@ -52,11 +71,9 @@ static void insert_one_record(struct shortlog *log,
strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
item = string_list_insert(&log->list, namemailbuf.buf);
if (item->util == NULL)
item->util = xcalloc(1, sizeof(struct string_list));
if (log->summary)
string_list_append(item->util, xstrdup(""));
item->util = (void *)(UTIL_TO_INT(item) + 1);
else {
const char *dot3 = log->common_repo_prefix;
char *buffer, *p;
@ -90,6 +107,8 @@ static void insert_one_record(struct shortlog *log,
}
}
if (item->util == NULL)
item->util = xcalloc(1, sizeof(struct string_list));
string_list_append(item->util, buffer);
}
}
@ -295,14 +314,14 @@ void shortlog_output(struct shortlog *log)
if (log->sort_by_number)
qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
compare_by_number);
log->summary ? compare_by_counter : compare_by_list);
for (i = 0; i < log->list.nr; i++) {
struct string_list *onelines = log->list.items[i].util;
const struct string_list_item *item = &log->list.items[i];
if (log->summary) {
printf("%6d\t%s\n", onelines->nr, log->list.items[i].string);
printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string);
} else {
printf("%s (%d):\n", log->list.items[i].string, onelines->nr);
struct string_list *onelines = item->util;
printf("%s (%d):\n", item->string, onelines->nr);
for (j = onelines->nr - 1; j >= 0; j--) {
const char *msg = onelines->items[j].string;
@ -315,11 +334,11 @@ void shortlog_output(struct shortlog *log)
printf(" %s\n", msg);
}
putchar('\n');
onelines->strdup_strings = 1;
string_list_clear(onelines, 0);
free(onelines);
}
onelines->strdup_strings = 1;
string_list_clear(onelines, 0);
free(onelines);
log->list.items[i].util = NULL;
}