summaryrefslogtreecommitdiff
path: root/pretty.c
AgeCommit message (Collapse)AuthorFilesLines
2007-11-11--format=pretty: avoid calculating expensive expansions twiceLibravatar René Scharfe1-0/+32
As Jeff King remarked, format strings with duplicate placeholders can be slow to expand, because each instance is calculated anew. This patch makes use of the fact that format_commit_message() and its helper functions only ever add stuff to the end of the strbuf. For certain expensive placeholders, store the offset and length of their expansion with the strbuf at the first occurrence. Later they expansion result can simply be copied from there -- no malloc() or strdup() required. These certain placeholders are the abbreviated commit, tree and parent hashes, as the search for a unique abbreviated hash is quite costly. Here are the times for next (best of three runs): $ time git log --pretty=format:%h >/dev/null real 0m0.611s user 0m0.404s sys 0m0.204s $ time git log --pretty=format:%h%h%h%h >/dev/null real 0m1.206s user 0m0.744s sys 0m0.452s And here those with this patch (and the previous two); the speedup of the single placeholder case is just noise: $ time git log --pretty=format:%h >/dev/null real 0m0.608s user 0m0.416s sys 0m0.192s $ time git log --pretty=format:%h%h%h%h >/dev/null real 0m0.639s user 0m0.488s sys 0m0.140s Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-11--pretty=format: parse commit message only onceLibravatar René Scharfe1-42/+82
As Jeff King pointed out, some placeholder expansions are related to each other: the steps to calculate one go most of the way towards calculating the other, too. This patch makes format_commit_message() parse the commit message only once, remembering the position of each item. This speeds up handling of format strings containing multiple placeholders from the set %s, %a*, %c*, %e, %b. Here are the timings for the git version in next. The first one is to estimate the overhead of the caching, the second one is taken from http://svn.tue.mpg.de/tentakel/trunk/tentakel/Makefile as an example of a format string found in the wild. The times are the fastest of three consecutive runs in each case: $ time git log --pretty=format:%e >/dev/null real 0m0.381s user 0m0.340s sys 0m0.024s $ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null real 0m0.623s user 0m0.556s sys 0m0.052s And here the times with this patch: $ time git log --pretty=format:%e >/dev/null real 0m0.385s user 0m0.332s sys 0m0.040s $ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null real 0m0.563s user 0m0.504s sys 0m0.048s Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-09--pretty=format: on-demand format expansionLibravatar René Scharfe1-123/+153
Some of the --pretty=format placeholders expansions are expensive to calculate. This is made worse by the current code's use of interpolate(), which requires _all_ placeholders are to be prepared up front. One way to speed this up is to check which placeholders are present in the format string and to prepare only the expansions that are needed. That still leaves the allocation overhead of interpolate(). Another way is to use a callback based approach together with the strbuf library to keep allocations to a minimum and avoid string copies. That's what this patch does. It introduces a new strbuf function, strbuf_expand(). The function takes a format string, list of placeholder strings, a user supplied function 'fn', and an opaque pointer 'context' to tell 'fn' what thingy to operate on. The function 'fn' is expected to accept a strbuf, a parsed placeholder string and the 'context' pointer, and append the interpolated value for the 'context' thingy, according to the format specified by the placeholder. Thanks to Pierre Habouzit for his suggestion to use strchrnul() and the code surrounding its callsite. And thanks to Junio for most of this commit message. :) Here my measurements of most of Paul Mackerras' test cases that highlighted the performance problem (best of three runs): (master) $ time git log --pretty=oneline >/dev/null real 0m0.390s user 0m0.340s sys 0m0.040s (master) $ time git log --pretty=raw >/dev/null real 0m0.434s user 0m0.408s sys 0m0.016s (master) $ time git log --pretty="format:%H {%P} %ct" >/dev/null real 0m1.347s user 0m0.080s sys 0m1.256s (interp_find_active -- Dscho) $ time ./git log --pretty="format:%H {%P} %ct" >/dev/null real 0m0.694s user 0m0.020s sys 0m0.672s (strbuf_expand -- this patch) $ time ./git log --pretty="format:%H {%P} %ct" >/dev/null real 0m0.395s user 0m0.352s sys 0m0.028s Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-11-05Split off the pretty print stuff into its own fileLibravatar Johannes Schindelin1-0/+723
The file commit.c got quite large, but it does not have to be: the code concerning pretty printing is pretty well contained. In fact, this commit just splits it off into pretty.c, leaving commit.c with just 672 lines. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>