{"thread":{"id":"14973","subject":"[PATCH 2/2] Use strbuf for struct xdiff_emit_state's remainder","startedAt":"2008-08-13T07:07:19Z","lastAt":"2008-08-13T07:07:19Z","messageCount":1,"participants":["Brian Downing"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"87016","messageId":"20080813070719.GC4396@lavos.net","threadId":"14973","inReplyTo":null,"subject":"[PATCH 2/2] Use strbuf for struct xdiff_emit_state's remainder","fromName":"Brian Downing","fromEmail":"bdowning@lavos.net","sentAt":"2008-08-13T07:07:19Z","receivedAt":"2008-08-13T07:07:19Z","isPatch":true,"sender":{"key":"bdowning@lavos.net","avatar":"https://avatars.githubusercontent.com/u/366426?v=4"},"body":"Continually xreallocing and freeing the remainder member of struct\nxdiff_emit_state was a noticeable performance hit.  Use a strbuf\ninstead.\n\nThis yields a decent performance improvement on \"git blame\" on certain\nrepositories.  For example, before this commit:\n\n$ time git blame -M -C -C -p --incremental server.c >/dev/null\n101.52user 0.17system 1:41.73elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k\n0inputs+0outputs (0major+39561minor)pagefaults 0swaps\n\nWith this commit:\n\n$ time git blame -M -C -C -p --incremental server.c >/dev/null\n80.38user 0.30system 1:20.81elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k\n0inputs+0outputs (0major+50979minor)pagefaults 0swaps\n\nSigned-off-by: Brian Downing <bdowning@lavos.net>\n---\n xdiff-interface.c |   33 +++++++++++----------------------\n xdiff-interface.h |    4 ++--\n 2 files changed, 13 insertions(+), 24 deletions(-)\n\ndiff --git a/xdiff-interface.c b/xdiff-interface.c\nindex 9c5e277..4462177 100644\n--- a/xdiff-interface.c\n+++ b/xdiff-interface.c\n@@ -66,6 +66,7 @@ void xdiff_outf_init(xdemitcb_t *ecb, void *priv_)\n \tstruct xdiff_emit_state *priv = priv_;\n \tecb->outf = xdiff_outf;\n \tecb->priv = priv;\n+\tstrbuf_init(&priv->remainder, 0);\n }\n \n int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)\n@@ -76,42 +77,30 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)\n \tfor (i = 0; i < nbuf; i++) {\n \t\tif (mb[i].ptr[mb[i].size-1] != '\\n') {\n \t\t\t/* Incomplete line */\n-\t\t\tpriv->remainder = xrealloc(priv->remainder,\n-\t\t\t\t\t\t   priv->remainder_size +\n-\t\t\t\t\t\t   mb[i].size);\n-\t\t\tmemcpy(priv->remainder + priv->remainder_size,\n-\t\t\t       mb[i].ptr, mb[i].size);\n-\t\t\tpriv->remainder_size += mb[i].size;\n+\t\t\tstrbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);\n \t\t\tcontinue;\n \t\t}\n \n \t\t/* we have a complete line */\n-\t\tif (!priv->remainder) {\n+\t\tif (!priv->remainder.len) {\n \t\t\tconsume_one(priv, mb[i].ptr, mb[i].size);\n \t\t\tcontinue;\n \t\t}\n-\t\tpriv->remainder = xrealloc(priv->remainder,\n-\t\t\t\t\t   priv->remainder_size +\n-\t\t\t\t\t   mb[i].size);\n-\t\tmemcpy(priv->remainder + priv->remainder_size,\n-\t\t       mb[i].ptr, mb[i].size);\n-\t\tconsume_one(priv, priv->remainder,\n-\t\t\t    priv->remainder_size + mb[i].size);\n-\t\tfree(priv->remainder);\n-\t\tpriv->remainder = NULL;\n-\t\tpriv->remainder_size = 0;\n+\t\tstrbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);\n+\t\tconsume_one(priv, priv->remainder.buf, priv->remainder.len);\n+\t\tstrbuf_reset(&priv->remainder);\n \t}\n-\tif (priv->remainder) {\n-\t\tconsume_one(priv, priv->remainder, priv->remainder_size);\n-\t\tfree(priv->remainder);\n-\t\tpriv->remainder = NULL;\n-\t\tpriv->remainder_size = 0;\n+\tif (priv->remainder.len) {\n+\t\tconsume_one(priv, priv->remainder.buf, priv->remainder.len);\n+\t\tstrbuf_reset(&priv->remainder);\n \t}\n \treturn 0;\n }\n \n void xdiff_outf_release(void *priv_)\n {\n+\tstruct xdiff_emit_state *priv = priv_;\n+\tstrbuf_release(&priv->remainder);\n }\n \n /*\ndiff --git a/xdiff-interface.h b/xdiff-interface.h\nindex fca6200..9b7e4a8 100644\n--- a/xdiff-interface.h\n+++ b/xdiff-interface.h\n@@ -2,6 +2,7 @@\n #define XDIFF_INTERFACE_H\n \n #include \"xdiff/xdiff.h\"\n+#include \"strbuf.h\"\n \n struct xdiff_emit_state;\n \n@@ -9,8 +10,7 @@ typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long);\n \n struct xdiff_emit_state {\n \txdiff_emit_consume_fn consume;\n-\tchar *remainder;\n-\tunsigned long remainder_size;\n+\tstruct strbuf remainder;\n };\n \n int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);\n-- \n1.5.6.1\n"}]}