{"thread":{"id":"35799","subject":"[PATCH] blame.c: prepare_lines should not call xrealloc for every line","startedAt":"2014-02-04T21:46:32Z","lastAt":"2014-02-04T21:46:32Z","messageCount":1,"participants":["David Kastrup"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"234236","messageId":"1391550392-17118-1-git-send-email-dak@gnu.org","threadId":"35799","inReplyTo":null,"subject":"[PATCH] blame.c: prepare_lines should not call xrealloc for every line","fromName":"David Kastrup","fromEmail":"dak@gnu.org","sentAt":"2014-02-04T21:46:32Z","receivedAt":"2014-02-04T21:46:32Z","isPatch":true,"sender":{"key":"dak@gnu.org","avatar":"https://avatars.githubusercontent.com/u/52141349?v=4"},"body":"Making a single preparation run for counting the lines will avoid memory\nfragmentation.  Also, fix the allocated memory size which was wrong\nwhen sizeof(int *) != sizeof(int), and would have been too small\nfor sizeof(int *) < sizeof(int), admittedly unlikely.\n\nSigned-off-by: David Kastrup <dak@gnu.org>\n---\n\nNow without including git-compat-util.h (included by cache.h already).\n\nbuiltin/blame.c | 43 ++++++++++++++++++++++++++++---------------\n 1 file changed, 28 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex e44a6bb..59d62dc 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -1772,25 +1772,38 @@ static int prepare_lines(struct scoreboard *sb)\n {\n \tconst char *buf = sb->final_buf;\n \tunsigned long len = sb->final_buf_size;\n-\tint num = 0, incomplete = 0, bol = 1;\n+\tconst char *end = buf + len;\n+\tconst char *p;\n+\tint *lineno;\n+\tint num = 0, incomplete = 0;\n \n-\tif (len && buf[len-1] != '\\n')\n-\t\tincomplete++; /* incomplete line at the end */\n-\twhile (len--) {\n-\t\tif (bol) {\n-\t\t\tsb->lineno = xrealloc(sb->lineno,\n-\t\t\t\t\t      sizeof(int *) * (num + 1));\n-\t\t\tsb->lineno[num] = buf - sb->final_buf;\n-\t\t\tbol = 0;\n+\tfor (p = buf;; num++) {\n+\t\tp = memchr(p, '\\n', end - p);\n+\t\tif (p) {\n+\t\t\tp++;\n+\t\t\tcontinue;\n \t\t}\n-\t\tif (*buf++ == '\\n') {\n-\t\t\tnum++;\n-\t\t\tbol = 1;\n+\t\tbreak;\n+\t}\n+\n+\tif (len && end[-1] != '\\n')\n+\t\tincomplete++; /* incomplete line at the end */\n+\n+\tsb->lineno = lineno = xmalloc(sizeof(int) * (num + incomplete + 1));\n+\n+\tfor (p = buf;;) {\n+\t\t*lineno++ = p - buf;\n+\t\tp = memchr(p, '\\n', end - p);\n+\t\tif (p) {\n+\t\t\tp++;\n+\t\t\tcontinue;\n \t\t}\n+\t\tbreak;\n \t}\n-\tsb->lineno = xrealloc(sb->lineno,\n-\t\t\t      sizeof(int *) * (num + incomplete + 1));\n-\tsb->lineno[num + incomplete] = buf - sb->final_buf;\n+\n+\tif (incomplete)\n+\t\t*lineno++ = len;\n+\n \tsb->num_lines = num + incomplete;\n \treturn sb->num_lines;\n }\n-- \n1.8.3.2\n"}]}