@matheusbsbs / matheus-bagliano / commits / 6a87ed972c
Fork 0

index-pack: smarter memory usage during delta resolution

There is no need to keep the base object data around after its last delta has been resolved. This also means that long delta chains with only one delta per base won't grow the cache size unnecessarily as the base will be freed before recursing down. To make it easy, find_delta_children() is modified so the first and last indices are initialized in all cases. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nicolas Pitre committed Oct 17, 2008 at 15:57 UTC 6a87ed972c9c7a4b4378b6e34670d3aa2ac7ccc8
1 file changed +39 -34
index-pack.c
+39 -34
@@ -221,17 +221,23 @@ static void bad_object(unsigned long offset, const char *format, ...)
221 die("pack has bad object at offset %lu: %s", offset, buf);
222 }
223
224 +static void free_base_data(struct base_data *c)
225 +{
226 + if (c->data) {
227 + free(c->data);
228 + c->data = NULL;
229 + base_cache_used -= c->size;
230 + }
231 +}
232 +
233 static void prune_base_data(struct base_data *retain)
234 {
235 struct base_data *b = base_cache;
236 for (b = base_cache;
237 base_cache_used > delta_base_cache_limit && b;
238 b = b->child) {
230 - if (b->data && b != retain) {
231 - free(b->data);
232 - b->data = NULL;
233 - base_cache_used -= b->size;
234 - }
239 + if (b->data && b != retain)
240 + free_base_data(b);
241 }
242 }
243
@@ -256,10 +262,7 @@ static void unlink_base_data(struct base_data *c)
262 base->child = NULL;
263 else
264 base_cache = NULL;
259 - if (c->data) {
260 - free(c->data);
261 - base_cache_used -= c->size;
262 - }
265 + free_base_data(c);
266 }
267
268 static void *unpack_entry_data(unsigned long offset, unsigned long size)
@@ -409,22 +412,24 @@ static int find_delta(const union delta_base *base)
412 return -first-1;
413 }
414
412 -static int find_delta_children(const union delta_base *base,
413 - int *first_index, int *last_index)
415 +static void find_delta_children(const union delta_base *base,
416 + int *first_index, int *last_index)
417 {
418 int first = find_delta(base);
419 int last = first;
420 int end = nr_deltas - 1;
421
419 - if (first < 0)
420 - return -1;
422 + if (first < 0) {
423 + *first_index = 0;
424 + *last_index = -1;
425 + return;
426 + }
427 while (first > 0 && !memcmp(&deltas[first - 1].base, base, UNION_BASE_SZ))
428 --first;
429 while (last < end && !memcmp(&deltas[last + 1].base, base, UNION_BASE_SZ))
430 ++last;
431 *first_index = first;
432 *last_index = last;
427 - return 0;
433 }
434
435 static void sha1_object(const void *data, unsigned long size,
@@ -529,7 +534,7 @@ static void resolve_delta(struct object_entry *delta_obj,
534 static void find_unresolved_deltas(struct base_data *base,
535 struct base_data *prev_base)
536 {
532 - int i, ref, ref_first, ref_last, ofs, ofs_first, ofs_last;
537 + int i, ref_first, ref_last, ofs_first, ofs_last;
538
539 /*
540 * This is a recursive function. Those brackets should help reducing
@@ -539,37 +544,37 @@ static void find_unresolved_deltas(struct base_data *base,
544 union delta_base base_spec;
545
546 hashcpy(base_spec.sha1, base->obj->idx.sha1);
542 - ref = !find_delta_children(&base_spec, &ref_first, &ref_last);
547 + find_delta_children(&base_spec, &ref_first, &ref_last);
548
549 memset(&base_spec, 0, sizeof(base_spec));
550 base_spec.offset = base->obj->idx.offset;
546 - ofs = !find_delta_children(&base_spec, &ofs_first, &ofs_last);
551 + find_delta_children(&base_spec, &ofs_first, &ofs_last);
552 }
553
549 - if (!ref && !ofs)
554 + if (ref_last == -1 && ofs_last == -1)
555 return;
556
557 link_base_data(prev_base, base);
558
554 - if (ref) {
555 - for (i = ref_first; i <= ref_last; i++) {
556 - struct object_entry *child = objects + deltas[i].obj_no;
557 - if (child->real_type == OBJ_REF_DELTA) {
558 - struct base_data result;
559 - resolve_delta(child, base, &result);
560 - find_unresolved_deltas(&result, base);
561 - }
559 + for (i = ref_first; i <= ref_last; i++) {
560 + struct object_entry *child = objects + deltas[i].obj_no;
561 + if (child->real_type == OBJ_REF_DELTA) {
562 + struct base_data result;
563 + resolve_delta(child, base, &result);
564 + if (i == ref_last && ofs_last == -1)
565 + free_base_data(base);
566 + find_unresolved_deltas(&result, base);
567 }
568 }
569
565 - if (ofs) {
566 - for (i = ofs_first; i <= ofs_last; i++) {
567 - struct object_entry *child = objects + deltas[i].obj_no;
568 - if (child->real_type == OBJ_OFS_DELTA) {
569 - struct base_data result;
570 - resolve_delta(child, base, &result);
571 - find_unresolved_deltas(&result, base);
572 - }
570 + for (i = ofs_first; i <= ofs_last; i++) {
571 + struct object_entry *child = objects + deltas[i].obj_no;
572 + if (child->real_type == OBJ_OFS_DELTA) {
573 + struct base_data result;
574 + resolve_delta(child, base, &result);
575 + if (i == ofs_last)
576 + free_base_data(base);
577 + find_unresolved_deltas(&result, base);
578 }
579 }
580