@@ -706,15 +706,28 @@ fn snapshots_share_no_node_ids(
706706 return false ;
707707 }
708708 // Overlap check is intentionally class-agnostic: an object can change
709- // class name across snapshots, but its ID cannot.
710- let base_nodes_count: usize = base. values ( ) . map ( |a| a. nodes . len ( ) ) . sum ( ) ;
711- let mut base_ids: std:: collections:: HashSet < u64 > =
712- std:: collections:: HashSet :: with_capacity ( base_nodes_count) ;
713- base_ids. extend ( base. values ( ) . flat_map ( |a| a. nodes . keys ( ) . copied ( ) ) ) ;
714- !current
715- . values ( )
716- . flat_map ( |a| a. nodes . keys ( ) )
717- . any ( |id| base_ids. contains ( id) )
709+ // class name across snapshots, but its ID cannot. Build the HashSet from
710+ // whichever side has fewer IDs, then scan the other — this bounds the
711+ // peak allocation to the smaller set for large snapshots.
712+ let base_count: usize = base. values ( ) . map ( |a| a. nodes . len ( ) ) . sum ( ) ;
713+ let current_count: usize = current. values ( ) . map ( |a| a. nodes . len ( ) ) . sum ( ) ;
714+ if base_count <= current_count {
715+ let mut ids: std:: collections:: HashSet < u64 > =
716+ std:: collections:: HashSet :: with_capacity ( base_count) ;
717+ ids. extend ( base. values ( ) . flat_map ( |a| a. nodes . keys ( ) . copied ( ) ) ) ;
718+ !current
719+ . values ( )
720+ . flat_map ( |a| a. nodes . keys ( ) )
721+ . any ( |id| ids. contains ( id) )
722+ } else {
723+ let mut ids: std:: collections:: HashSet < u64 > =
724+ std:: collections:: HashSet :: with_capacity ( current_count) ;
725+ ids. extend ( current. values ( ) . flat_map ( |a| a. nodes . keys ( ) . copied ( ) ) ) ;
726+ !base
727+ . values ( )
728+ . flat_map ( |a| a. nodes . keys ( ) )
729+ . any ( |id| ids. contains ( id) )
730+ }
718731}
719732
720733/// Offline implementation of `compare-heapsnapshots`. Parses both files,
0 commit comments