{"thread":{"id":"4726","subject":"[PATCH] don't load objects needlessly when repacking","startedAt":"2006-07-01T02:55:30Z","lastAt":"2006-07-01T02:55:30Z","messageCount":1,"participants":["Nicolas Pitre"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"22963","messageId":"Pine.LNX.4.64.0606302243120.1213@localhost.localdomain","threadId":"4726","inReplyTo":null,"subject":"[PATCH] don't load objects needlessly when repacking","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2006-07-01T02:55:30Z","receivedAt":"2006-07-01T02:55:30Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"If no delta is attempted on some objects then it is useless to load them \nin memory, neither create any delta index for them.  The best thing to \ndo is therefore to load and index them only when really needed.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n\n---\n\nWith this patch, a git-repack -a on the Linux kernel repo takes 19 \nseconds instead of 25 seconds on my machine.  At this point the cost of \ncreating a pack is largely dominated by git-rev-list alone while the \nactual pack creation is basically free.\n\ndiff --git a/pack-objects.c b/pack-objects.c\nindex 47da33b..b486ea5 100644\n--- a/pack-objects.c\n+++ b/pack-objects.c\n@@ -970,11 +970,12 @@ struct unpacked {\n  * one.\n  */\n static int try_delta(struct unpacked *trg, struct unpacked *src,\n-\t\t     struct delta_index *src_index, unsigned max_depth)\n+\t\t     unsigned max_depth)\n {\n \tstruct object_entry *trg_entry = trg->entry;\n \tstruct object_entry *src_entry = src->entry;\n-\tunsigned long size, src_size, delta_size, sizediff, max_size;\n+\tunsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;\n+\tchar type[10];\n \tvoid *delta_buf;\n \n \t/* Don't bother doing diffs between different types */\n@@ -1009,19 +1010,38 @@ static int try_delta(struct unpacked *tr\n \t\treturn 0;\n \n \t/* Now some size filtering heuristics. */\n-\tsize = trg_entry->size;\n-\tmax_size = size/2 - 20;\n+\ttrg_size = trg_entry->size;\n+\tmax_size = trg_size/2 - 20;\n \tmax_size = max_size * (max_depth - src_entry->depth) / max_depth;\n \tif (max_size == 0)\n \t\treturn 0;\n \tif (trg_entry->delta && trg_entry->delta_size <= max_size)\n \t\tmax_size = trg_entry->delta_size-1;\n \tsrc_size = src_entry->size;\n-\tsizediff = src_size < size ? size - src_size : 0;\n+\tsizediff = src_size < trg_size ? trg_size - src_size : 0;\n \tif (sizediff >= max_size)\n \t\treturn 0;\n \n-\tdelta_buf = create_delta(src_index, trg->data, size, &delta_size, max_size);\n+\t/* Load data if not already done */\n+\tif (!trg->data) {\n+\t\ttrg->data = read_sha1_file(trg_entry->sha1, type, &sz);\n+\t\tif (sz != trg_size)\n+\t\t\tdie(\"object %s inconsistent object length (%lu vs %lu)\",\n+\t\t\t    sha1_to_hex(trg_entry->sha1), sz, trg_size);\n+\t}\n+\tif (!src->data) {\n+\t\tsrc->data = read_sha1_file(src_entry->sha1, type, &sz);\n+\t\tif (sz != src_size)\n+\t\t\tdie(\"object %s inconsistent object length (%lu vs %lu)\",\n+\t\t\t    sha1_to_hex(src_entry->sha1), sz, src_size);\n+\t}\n+\tif (!src->index) {\n+\t\tsrc->index = create_delta_index(src->data, src_size);\n+\t\tif (!src->index)\n+\t\t\tdie(\"out of memory\");\n+\t}\n+\n+\tdelta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size);\n \tif (!delta_buf)\n \t\treturn 0;\n \n@@ -1054,8 +1074,6 @@ static void find_deltas(struct object_en\n \twhile (--i >= 0) {\n \t\tstruct object_entry *entry = list[i];\n \t\tstruct unpacked *n = array + idx;\n-\t\tunsigned long size;\n-\t\tchar type[10];\n \t\tint j;\n \n \t\tif (!entry->preferred_base)\n@@ -1082,11 +1100,8 @@ static void find_deltas(struct object_en\n \t\tfree_delta_index(n->index);\n \t\tn->index = NULL;\n \t\tfree(n->data);\n+\t\tn->data = NULL;\n \t\tn->entry = entry;\n-\t\tn->data = read_sha1_file(entry->sha1, type, &size);\n-\t\tif (size != entry->size)\n-\t\t\tdie(\"object %s inconsistent object length (%lu vs %lu)\",\n-\t\t\t    sha1_to_hex(entry->sha1), size, entry->size);\n \n \t\tj = window;\n \t\twhile (--j > 0) {\n@@ -1097,7 +1112,7 @@ static void find_deltas(struct object_en\n \t\t\tm = array + other_idx;\n \t\t\tif (!m->entry)\n \t\t\t\tbreak;\n-\t\t\tif (try_delta(n, m, m->index, depth) < 0)\n+\t\t\tif (try_delta(n, m, depth) < 0)\n \t\t\t\tbreak;\n \t\t}\n \t\t/* if we made n a delta, and if n is already at max\n@@ -1107,10 +1122,6 @@ static void find_deltas(struct object_en\n \t\tif (entry->delta && depth <= entry->depth)\n \t\t\tcontinue;\n \n-\t\tn->index = create_delta_index(n->data, size);\n-\t\tif (!n->index)\n-\t\t\tdie(\"out of memory\");\n-\n \t\tidx++;\n \t\tif (idx >= window)\n \t\t\tidx = 0;\n"}]}