@@ -317,10 +317,11 @@ static int find_identical_files(struct hashmap *srcs,
317
317
}
318
318
319
319
static void insert_file_table (struct repository * r ,
320
+ struct mem_pool * pool ,
320
321
struct hashmap * table , int index ,
321
322
struct diff_filespec * filespec )
322
323
{
323
- struct file_similarity * entry = xmalloc ( sizeof (* entry ));
324
+ struct file_similarity * entry = mem_pool_alloc ( pool , sizeof (* entry ));
324
325
325
326
entry -> index = index ;
326
327
entry -> filespec = filespec ;
@@ -336,7 +337,8 @@ static void insert_file_table(struct repository *r,
336
337
* and then during the second round we try to match
337
338
* cache-dirty entries as well.
338
339
*/
339
- static int find_exact_renames (struct diff_options * options )
340
+ static int find_exact_renames (struct diff_options * options ,
341
+ struct mem_pool * pool )
340
342
{
341
343
int i , renames = 0 ;
342
344
struct hashmap file_table ;
@@ -346,16 +348,16 @@ static int find_exact_renames(struct diff_options *options)
346
348
*/
347
349
hashmap_init (& file_table , NULL , NULL , rename_src_nr );
348
350
for (i = rename_src_nr - 1 ; i >= 0 ; i -- )
349
- insert_file_table (options -> repo ,
351
+ insert_file_table (options -> repo , pool ,
350
352
& file_table , i ,
351
353
rename_src [i ].p -> one );
352
354
353
355
/* Walk the destinations and find best source match */
354
356
for (i = 0 ; i < rename_dst_nr ; i ++ )
355
357
renames += find_identical_files (& file_table , i , options );
356
358
357
- /* Free the hash data structure and entries */
358
- hashmap_clear_and_free (& file_table , struct file_similarity , entry );
359
+ /* Free the hash data structure ( entries will be freed with the pool) */
360
+ hashmap_clear (& file_table );
359
361
360
362
return renames ;
361
363
}
@@ -1330,7 +1332,47 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
1330
1332
rename_src_nr = new_num_src ;
1331
1333
}
1332
1334
1335
+ static void free_filespec_data (struct diff_filespec * spec )
1336
+ {
1337
+ if (!-- spec -> count )
1338
+ diff_free_filespec_data (spec );
1339
+ }
1340
+
1341
+ static void pool_free_filespec (struct mem_pool * pool ,
1342
+ struct diff_filespec * spec )
1343
+ {
1344
+ if (!pool ) {
1345
+ free_filespec (spec );
1346
+ return ;
1347
+ }
1348
+
1349
+ /*
1350
+ * Similar to free_filespec(), but only frees the data. The spec
1351
+ * itself was allocated in the pool and should not be individually
1352
+ * freed.
1353
+ */
1354
+ free_filespec_data (spec );
1355
+ }
1356
+
1357
+ void pool_diff_free_filepair (struct mem_pool * pool ,
1358
+ struct diff_filepair * p )
1359
+ {
1360
+ if (!pool ) {
1361
+ diff_free_filepair (p );
1362
+ return ;
1363
+ }
1364
+
1365
+ /*
1366
+ * Similar to diff_free_filepair() but only frees the data from the
1367
+ * filespecs; not the filespecs or the filepair which were
1368
+ * allocated from the pool.
1369
+ */
1370
+ free_filespec_data (p -> one );
1371
+ free_filespec_data (p -> two );
1372
+ }
1373
+
1333
1374
void diffcore_rename_extended (struct diff_options * options ,
1375
+ struct mem_pool * pool ,
1334
1376
struct strintmap * relevant_sources ,
1335
1377
struct strintmap * dirs_removed ,
1336
1378
struct strmap * dir_rename_count ,
@@ -1345,6 +1387,7 @@ void diffcore_rename_extended(struct diff_options *options,
1345
1387
int num_destinations , dst_cnt ;
1346
1388
int num_sources , want_copies ;
1347
1389
struct progress * progress = NULL ;
1390
+ struct mem_pool local_pool ;
1348
1391
struct dir_rename_info info ;
1349
1392
struct diff_populate_filespec_options dpf_options = {
1350
1393
.check_binary = 0 ,
@@ -1413,11 +1456,18 @@ void diffcore_rename_extended(struct diff_options *options,
1413
1456
goto cleanup ; /* nothing to do */
1414
1457
1415
1458
trace2_region_enter ("diff" , "exact renames" , options -> repo );
1459
+ mem_pool_init (& local_pool , 32 * 1024 );
1416
1460
/*
1417
1461
* We really want to cull the candidates list early
1418
1462
* with cheap tests in order to avoid doing deltas.
1419
1463
*/
1420
- rename_count = find_exact_renames (options );
1464
+ rename_count = find_exact_renames (options , & local_pool );
1465
+ /*
1466
+ * Discard local_pool immediately instead of at "cleanup:" in order
1467
+ * to reduce maximum memory usage; inexact rename detection uses up
1468
+ * a fair amount of memory, and mem_pools can too.
1469
+ */
1470
+ mem_pool_discard (& local_pool , 0 );
1421
1471
trace2_region_leave ("diff" , "exact renames" , options -> repo );
1422
1472
1423
1473
/* Did we only want exact renames? */
@@ -1636,7 +1686,7 @@ void diffcore_rename_extended(struct diff_options *options,
1636
1686
pair_to_free = p ;
1637
1687
1638
1688
if (pair_to_free )
1639
- diff_free_filepair ( pair_to_free );
1689
+ pool_diff_free_filepair ( pool , pair_to_free );
1640
1690
}
1641
1691
diff_debug_queue ("done copying original" , & outq );
1642
1692
@@ -1646,7 +1696,7 @@ void diffcore_rename_extended(struct diff_options *options,
1646
1696
1647
1697
for (i = 0 ; i < rename_dst_nr ; i ++ )
1648
1698
if (rename_dst [i ].filespec_to_free )
1649
- free_filespec ( rename_dst [i ].filespec_to_free );
1699
+ pool_free_filespec ( pool , rename_dst [i ].filespec_to_free );
1650
1700
1651
1701
cleanup_dir_rename_info (& info , dirs_removed , dir_rename_count != NULL );
1652
1702
FREE_AND_NULL (rename_dst );
@@ -1663,5 +1713,5 @@ void diffcore_rename_extended(struct diff_options *options,
1663
1713
1664
1714
void diffcore_rename (struct diff_options * options )
1665
1715
{
1666
- diffcore_rename_extended (options , NULL , NULL , NULL , NULL );
1716
+ diffcore_rename_extended (options , NULL , NULL , NULL , NULL , NULL );
1667
1717
}
0 commit comments