@@ -604,12 +604,18 @@ static int switch_cache_bottom(struct traverse_info *info)
604
604
return ret ;
605
605
}
606
606
607
+ static inline int are_same_oid (struct name_entry * name_j , struct name_entry * name_k )
608
+ {
609
+ return name_j -> oid && name_k -> oid && !oidcmp (name_j -> oid , name_k -> oid );
610
+ }
611
+
607
612
static int traverse_trees_recursive (int n , unsigned long dirmask ,
608
613
unsigned long df_conflicts ,
609
614
struct name_entry * names ,
610
615
struct traverse_info * info )
611
616
{
612
617
int i , ret , bottom ;
618
+ int nr_buf = 0 ;
613
619
struct tree_desc t [MAX_UNPACK_TREES ];
614
620
void * buf [MAX_UNPACK_TREES ];
615
621
struct traverse_info newinfo ;
@@ -626,18 +632,40 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
626
632
newinfo .pathlen += tree_entry_len (p ) + 1 ;
627
633
newinfo .df_conflicts |= df_conflicts ;
628
634
635
+ /*
636
+ * Fetch the tree from the ODB for each peer directory in the
637
+ * n commits.
638
+ *
639
+ * For 2- and 3-way traversals, we try to avoid hitting the
640
+ * ODB twice for the same OID. This should yield a nice speed
641
+ * up in checkouts and merges when the commits are similar.
642
+ *
643
+ * We don't bother doing the full O(n^2) search for larger n,
644
+ * because wider traversals don't happen that often and we
645
+ * avoid the search setup.
646
+ *
647
+ * When 2 peer OIDs are the same, we just copy the tree
648
+ * descriptor data. This implicitly borrows the buffer
649
+ * data from the earlier cell.
650
+ */
629
651
for (i = 0 ; i < n ; i ++ , dirmask >>= 1 ) {
630
- const unsigned char * sha1 = NULL ;
631
- if (dirmask & 1 )
632
- sha1 = names [i ].oid -> hash ;
633
- buf [i ] = fill_tree_descriptor (t + i , sha1 );
652
+ if (i > 0 && are_same_oid (& names [i ], & names [i - 1 ]))
653
+ t [i ] = t [i - 1 ];
654
+ else if (i > 1 && are_same_oid (& names [i ], & names [i - 2 ]))
655
+ t [i ] = t [i - 2 ];
656
+ else {
657
+ const unsigned char * sha1 = NULL ;
658
+ if (dirmask & 1 )
659
+ sha1 = names [i ].oid -> hash ;
660
+ buf [nr_buf ++ ] = fill_tree_descriptor (t + i , sha1 );
661
+ }
634
662
}
635
663
636
664
bottom = switch_cache_bottom (& newinfo );
637
665
ret = traverse_trees (n , t , & newinfo );
638
666
restore_cache_bottom (& newinfo , bottom );
639
667
640
- for (i = 0 ; i < n ; i ++ )
668
+ for (i = 0 ; i < nr_buf ; i ++ )
641
669
free (buf [i ]);
642
670
643
671
return ret ;
0 commit comments