Continually xreallocing and freeing the remainder member of struct xdiff_emit_state was a noticeable performance hit. Use a strbuf instead. This yields a decent performance improvement on "git blame" on certain repositories. For example, before this commit: $ time git blame -M -C -C -p --incremental server.c >/dev/null 101.52user 0.17system 1:41.73elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+39561minor)pagefaults 0swaps With this commit: $ time git blame -M -C -C -p --incremental server.c >/dev/null 80.38user 0.30system 1:20.81elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+50979minor)pagefaults 0swaps Signed-off-by: Brian Downing <bdowning@xxxxxxxxx> --- xdiff-interface.c | 33 +++++++++++---------------------- xdiff-interface.h | 4 ++-- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/xdiff-interface.c b/xdiff-interface.c index 9c5e277..4462177 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -66,6 +66,7 @@ void xdiff_outf_init(xdemitcb_t *ecb, void *priv_) struct xdiff_emit_state *priv = priv_; ecb->outf = xdiff_outf; ecb->priv = priv; + strbuf_init(&priv->remainder, 0); } int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) @@ -76,42 +77,30 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) for (i = 0; i < nbuf; i++) { if (mb[i].ptr[mb[i].size-1] != '\n') { /* Incomplete line */ - priv->remainder = xrealloc(priv->remainder, - priv->remainder_size + - mb[i].size); - memcpy(priv->remainder + priv->remainder_size, - mb[i].ptr, mb[i].size); - priv->remainder_size += mb[i].size; + strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size); continue; } /* we have a complete line */ - if (!priv->remainder) { + if (!priv->remainder.len) { consume_one(priv, mb[i].ptr, mb[i].size); continue; } - priv->remainder = xrealloc(priv->remainder, - priv->remainder_size + - mb[i].size); - memcpy(priv->remainder + priv->remainder_size, - mb[i].ptr, mb[i].size); - consume_one(priv, priv->remainder, - priv->remainder_size + mb[i].size); - free(priv->remainder); - priv->remainder = NULL; - priv->remainder_size = 0; + strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size); + consume_one(priv, priv->remainder.buf, priv->remainder.len); + strbuf_reset(&priv->remainder); } - if (priv->remainder) { - consume_one(priv, priv->remainder, priv->remainder_size); - free(priv->remainder); - priv->remainder = NULL; - priv->remainder_size = 0; + if (priv->remainder.len) { + consume_one(priv, priv->remainder.buf, priv->remainder.len); + strbuf_reset(&priv->remainder); } return 0; } void xdiff_outf_release(void *priv_) { + struct xdiff_emit_state *priv = priv_; + strbuf_release(&priv->remainder); } /* diff --git a/xdiff-interface.h b/xdiff-interface.h index fca6200..9b7e4a8 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -2,6 +2,7 @@ #define XDIFF_INTERFACE_H #include "xdiff/xdiff.h" +#include "strbuf.h" struct xdiff_emit_state; @@ -9,8 +10,7 @@ typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long); struct xdiff_emit_state { xdiff_emit_consume_fn consume; - char *remainder; - unsigned long remainder_size; + struct strbuf remainder; }; int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb); -- 1.5.6.1 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html