@@ -36,6 +36,7 @@ struct object_entry {
36
36
struct object_entry * delta_sibling ; /* other deltified objects who
37
37
* uses the same base as me
38
38
*/
39
+ void * delta_data ; /* cached delta (uncompressed) */
39
40
unsigned long delta_size ; /* delta data size (uncompressed) */
40
41
enum object_type type ;
41
42
enum object_type in_pack_type ; /* could be delta */
@@ -76,6 +77,10 @@ static struct progress progress_state;
76
77
static int pack_compression_level = Z_DEFAULT_COMPRESSION ;
77
78
static int pack_compression_seen ;
78
79
80
+ static unsigned long delta_cache_size = 0 ;
81
+ static unsigned long max_delta_cache_size = 0 ;
82
+ static unsigned long cache_max_small_delta_size = 1000 ;
83
+
79
84
/*
80
85
* The object names in objects array are hashed with this hashtable,
81
86
* to help looking up the entry by object name.
@@ -405,24 +410,24 @@ static unsigned long write_object(struct sha1file *f,
405
410
z_stream stream ;
406
411
unsigned long maxsize ;
407
412
void * out ;
408
- buf = read_sha1_file (entry -> sha1 , & type , & size );
409
- if (!buf )
410
- die ("unable to read %s" , sha1_to_hex (entry -> sha1 ));
411
- if (size != entry -> size )
412
- die ("object %s size inconsistency (%lu vs %lu)" ,
413
- sha1_to_hex (entry -> sha1 ), size , entry -> size );
414
- if (usable_delta ) {
415
- buf = delta_against (buf , size , entry );
413
+ if (!usable_delta ) {
414
+ buf = read_sha1_file (entry -> sha1 , & obj_type , & size );
415
+ if (!buf )
416
+ die ("unable to read %s" , sha1_to_hex (entry -> sha1 ));
417
+ } else if (entry -> delta_data ) {
416
418
size = entry -> delta_size ;
419
+ buf = entry -> delta_data ;
420
+ entry -> delta_data = NULL ;
417
421
obj_type = (allow_ofs_delta && entry -> delta -> offset ) ?
418
422
OBJ_OFS_DELTA : OBJ_REF_DELTA ;
419
423
} else {
420
- /*
421
- * recover real object type in case
422
- * check_object() wanted to re-use a delta,
423
- * but we couldn't since base was in previous split pack
424
- */
425
- obj_type = type ;
424
+ buf = read_sha1_file (entry -> sha1 , & type , & size );
425
+ if (!buf )
426
+ die ("unable to read %s" , sha1_to_hex (entry -> sha1 ));
427
+ buf = delta_against (buf , size , entry );
428
+ size = entry -> delta_size ;
429
+ obj_type = (allow_ofs_delta && entry -> delta -> offset ) ?
430
+ OBJ_OFS_DELTA : OBJ_REF_DELTA ;
426
431
}
427
432
/* compress the data to store and put compressed length in datalen */
428
433
memset (& stream , 0 , sizeof (stream ));
@@ -1385,6 +1390,23 @@ struct unpacked {
1385
1390
struct delta_index * index ;
1386
1391
};
1387
1392
1393
+ static int delta_cacheable (struct unpacked * trg , struct unpacked * src ,
1394
+ unsigned long src_size , unsigned long trg_size ,
1395
+ unsigned long delta_size )
1396
+ {
1397
+ if (max_delta_cache_size && delta_cache_size + delta_size > max_delta_cache_size )
1398
+ return 0 ;
1399
+
1400
+ if (delta_size < cache_max_small_delta_size )
1401
+ return 1 ;
1402
+
1403
+ /* cache delta, if objects are large enough compared to delta size */
1404
+ if ((src_size >> 20 ) + (trg_size >> 21 ) > (delta_size >> 10 ))
1405
+ return 1 ;
1406
+
1407
+ return 0 ;
1408
+ }
1409
+
1388
1410
/*
1389
1411
* We search for deltas _backwards_ in a list sorted by type and
1390
1412
* by size, so that we see progressively smaller and smaller files.
@@ -1454,18 +1476,32 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
1454
1476
}
1455
1477
if (!src -> index ) {
1456
1478
src -> index = create_delta_index (src -> data , src_size );
1457
- if (!src -> index )
1458
- die ("out of memory" );
1479
+ if (!src -> index ) {
1480
+ static int warned = 0 ;
1481
+ if (!warned ++ )
1482
+ warning ("suboptimal pack - out of memory" );
1483
+ return 0 ;
1484
+ }
1459
1485
}
1460
1486
1461
1487
delta_buf = create_delta (src -> index , trg -> data , trg_size , & delta_size , max_size );
1462
1488
if (!delta_buf )
1463
1489
return 0 ;
1464
1490
1491
+ if (trg_entry -> delta_data ) {
1492
+ delta_cache_size -= trg_entry -> delta_size ;
1493
+ free (trg_entry -> delta_data );
1494
+ }
1495
+ trg_entry -> delta_data = 0 ;
1465
1496
trg_entry -> delta = src_entry ;
1466
1497
trg_entry -> delta_size = delta_size ;
1467
1498
trg_entry -> depth = src_entry -> depth + 1 ;
1468
- free (delta_buf );
1499
+
1500
+ if (delta_cacheable (src , trg , src_size , trg_size , delta_size )) {
1501
+ trg_entry -> delta_data = xrealloc (delta_buf , delta_size );
1502
+ delta_cache_size += trg_entry -> delta_size ;
1503
+ } else
1504
+ free (delta_buf );
1469
1505
return 1 ;
1470
1506
}
1471
1507
@@ -1611,6 +1647,14 @@ static int git_pack_config(const char *k, const char *v)
1611
1647
pack_compression_seen = 1 ;
1612
1648
return 0 ;
1613
1649
}
1650
+ if (!strcmp (k , "pack.deltacachesize" )) {
1651
+ max_delta_cache_size = git_config_int (k , v );
1652
+ return 0 ;
1653
+ }
1654
+ if (!strcmp (k , "pack.deltacachelimit" )) {
1655
+ cache_max_small_delta_size = git_config_int (k , v );
1656
+ return 0 ;
1657
+ }
1614
1658
return git_default_config (k , v );
1615
1659
}
1616
1660
0 commit comments