@@ -259,6 +259,22 @@ fn ancestor_chain(dir: &str) -> Vec<String> {
259259 chain
260260}
261261
262+ // directory_distance is on the hot path for every call-edge confidence
263+ // score, invoked from inside compute_confidence's rayon `.par_iter()` caller
264+ // (line ~330 below). The same directory pairs recur constantly across a
265+ // build, so memoizing avoids rebuilding both ancestor chains and the lookup
266+ // map every call. Thread-local (not a shared Mutex/DashMap) because rayon's
267+ // worker pool is reused across the whole build — each worker accumulates its
268+ // own useful cache with zero lock contention, at the cost of some redundant
269+ // computation the first time a given pair is seen on each thread.
270+ // distance(a, b) === distance(b, a) (symmetric tree distance), so the key is
271+ // order-independent to halve the effective cache size per thread (#1769
272+ // perf regression).
273+ thread_local ! {
274+ static DIRECTORY_DISTANCE_CACHE : std:: cell:: RefCell <std:: collections:: HashMap <( String , String ) , usize >> =
275+ std:: cell:: RefCell :: new( std:: collections:: HashMap :: new( ) ) ;
276+ }
277+
262278/// Directory-tree distance between two directories: hops up from `a` to the
263279/// nearest ancestor shared with `b`, plus hops down from there to `b`.
264280///
@@ -271,16 +287,24 @@ fn ancestor_chain(dir: &str) -> Vec<String> {
271287/// so e.g. a file in `graph/algorithms/*.rs` calling a method declared in
272288/// the shallower `graph/model.rs` was scored as maximally distant (issue #1769).
273289fn directory_distance ( a : & str , b : & str ) -> usize {
290+ let key = if a <= b { ( a. to_string ( ) , b. to_string ( ) ) } else { ( b. to_string ( ) , a. to_string ( ) ) } ;
291+ if let Some ( cached) = DIRECTORY_DISTANCE_CACHE . with ( |c| c. borrow ( ) . get ( & key) . copied ( ) ) {
292+ return cached;
293+ }
294+
274295 let chain_a = ancestor_chain ( a) ;
275296 let chain_b = ancestor_chain ( b) ;
276297 let index_in_b: std:: collections:: HashMap < & str , usize > =
277298 chain_b. iter ( ) . enumerate ( ) . map ( |( j, d) | ( d. as_str ( ) , j) ) . collect ( ) ;
299+ let mut dist = usize:: MAX ;
278300 for ( i, dir_a) in chain_a. iter ( ) . enumerate ( ) {
279301 if let Some ( & j) = index_in_b. get ( dir_a. as_str ( ) ) {
280- return i + j;
302+ dist = i + j;
303+ break ;
281304 }
282305 }
283- usize:: MAX
306+ DIRECTORY_DISTANCE_CACHE . with ( |c| c. borrow_mut ( ) . insert ( key, dist) ) ;
307+ dist
284308}
285309
286310/// Compute proximity-based confidence for call resolution.
0 commit comments