@@ -604,12 +604,18 @@ static int switch_cache_bottom(struct traverse_info *info)
604604 return ret ;
605605}
606606
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+
607612static int traverse_trees_recursive (int n , unsigned long dirmask ,
608613 unsigned long df_conflicts ,
609614 struct name_entry * names ,
610615 struct traverse_info * info )
611616{
612617 int i , ret , bottom ;
618+ int nr_buf = 0 ;
613619 struct tree_desc t [MAX_UNPACK_TREES ];
614620 void * buf [MAX_UNPACK_TREES ];
615621 struct traverse_info newinfo ;
@@ -626,18 +632,40 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
626632 newinfo .pathlen += tree_entry_len (p ) + 1 ;
627633 newinfo .df_conflicts |= df_conflicts ;
628634
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+ */
629651 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+ }
634662 }
635663
636664 bottom = switch_cache_bottom (& newinfo );
637665 ret = traverse_trees (n , t , & newinfo );
638666 restore_cache_bottom (& newinfo , bottom );
639667
640- for (i = 0 ; i < n ; i ++ )
668+ for (i = 0 ; i < nr_buf ; i ++ )
641669 free (buf [i ]);
642670
643671 return ret ;
0 commit comments