{"thread":{"id":"35798","subject":"[PATCH] blame.c: prepare_lines should not call xrealloc for every line","startedAt":"2014-02-04T21:40:11Z","lastAt":"2014-02-04T21:40:11Z","messageCount":1,"participants":["David Kastrup"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"234233","messageId":"1391550011-17015-1-git-send-email-dak@gnu.org","threadId":"35798","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:40:11Z","receivedAt":"2014-02-04T21:40:11Z","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 builtin/blame.c | 44 +++++++++++++++++++++++++++++---------------\n 1 file changed, 29 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex e44a6bb..c422584 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -4,6 +4,7 @@\n  * Copyright (c) 2006, Junio C Hamano\n  */\n \n+#include \"git-compat-util.h\"\n #include \"cache.h\"\n #include \"builtin.h\"\n #include \"blob.h\"\n@@ -1772,25 +1773,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"}]}