@@ -12,23 +12,38 @@ use std::path::{Path, PathBuf};
1212
1313use super :: parse_perf_file:: { SymbolPidMappingWithFullPath , UnwindDataPidMappingWithFullPath } ;
1414
15+ /// Register a path in the map if absent, assigning a new unique key.
16+ /// Returns the assigned key.
17+ fn get_or_insert_key ( path_to_key : & mut HashMap < PathBuf , String > , path : & Path ) -> String {
18+ if let Some ( key) = path_to_key. get ( path) {
19+ return key. clone ( ) ;
20+ }
21+ let key = naming:: indexed_semantic_key ( path_to_key. len ( ) , path) ;
22+ path_to_key. insert ( path. to_owned ( ) , key. clone ( ) ) ;
23+ key
24+ }
25+
1526/// Save deduplicated symbol files to disk and build per-pid mappings using semantic keys.
1627pub fn save_symbols (
1728 profile_folder : & Path ,
1829 symbols_by_path : & HashMap < PathBuf , ModuleSymbols > ,
1930 pid_symbol_mappings_by_pid : & HashMap < i32 , Vec < SymbolPidMappingWithFullPath > > ,
31+ path_to_key : & mut HashMap < PathBuf , String > ,
2032) -> HashMap < i32 , Vec < SymbolPidMapping > > {
2133 debug ! ( "Saving symbols ({} unique entries)" , symbols_by_path. len( ) ) ;
2234
23- let path_to_key = build_path_to_key_map ( symbols_by_path. keys ( ) . map ( |p| p. to_string_lossy ( ) ) ) ;
35+ // Pre-register all paths so the parallel section can use immutable borrows
36+ for path in symbols_by_path. keys ( ) {
37+ get_or_insert_key ( path_to_key, path) ;
38+ }
2439
2540 symbols_by_path. par_iter ( ) . for_each ( |( path, module) | {
26- let key = & path_to_key[ & * path. to_string_lossy ( ) ] ;
41+ let key = & path_to_key[ path] ;
2742 module. save_to ( profile_folder, key) . unwrap ( ) ;
2843 } ) ;
2944
3045 convert_pid_mappings ( pid_symbol_mappings_by_pid, |m| {
31- let key = path_to_key. get ( & * m. path . to_string_lossy ( ) ) ?. clone ( ) ;
46+ let key = path_to_key. get ( & m. path ) ?. clone ( ) ;
3247 Some ( (
3348 key. clone ( ) ,
3449 SymbolPidMapping {
@@ -43,6 +58,7 @@ pub fn save_symbols(
4358pub fn save_debug_info (
4459 symbols_by_path : & HashMap < PathBuf , ModuleSymbols > ,
4560 pid_symbol_mappings_by_pid : & HashMap < i32 , Vec < SymbolPidMappingWithFullPath > > ,
61+ path_to_key : & mut HashMap < PathBuf , String > ,
4662) -> (
4763 HashMap < String , ModuleDebugInfo > ,
4864 HashMap < i32 , Vec < DebugInfoPidMapping > > ,
@@ -51,16 +67,21 @@ pub fn save_debug_info(
5167
5268 let debug_info_by_elf_path = debug_info_by_path ( symbols_by_path) ;
5369
54- let path_to_key =
55- build_path_to_key_map ( debug_info_by_elf_path. keys ( ) . map ( |p| p. to_string_lossy ( ) ) ) ;
70+ // Pre-register all paths so the closures below can use immutable borrows
71+ for path in debug_info_by_elf_path. keys ( ) {
72+ get_or_insert_key ( path_to_key, path) ;
73+ }
5674
5775 let debug_info: HashMap < String , ModuleDebugInfo > = debug_info_by_elf_path
5876 . into_iter ( )
59- . map ( |( path, info) | ( path_to_key[ & * path. to_string_lossy ( ) ] . clone ( ) , info) )
77+ . filter_map ( |( path, info) | {
78+ let key = path_to_key. get ( & path) ?. clone ( ) ;
79+ Some ( ( key, info) )
80+ } )
6081 . collect ( ) ;
6182
6283 let pid_mappings = convert_pid_mappings ( pid_symbol_mappings_by_pid, |m| {
63- let key = path_to_key. get ( & * m. path . to_string_lossy ( ) ) ?. clone ( ) ;
84+ let key = path_to_key. get ( & m. path ) ?. clone ( ) ;
6485 Some ( (
6586 key. clone ( ) ,
6687 DebugInfoPidMapping {
@@ -76,18 +97,22 @@ pub fn save_debug_info(
7697/// Save deduplicated unwind data files to disk and build per-pid mappings using semantic keys.
7798pub fn save_unwind_data (
7899 profile_folder : & Path ,
79- unwind_data_by_path : & HashMap < String , UnwindData > ,
100+ unwind_data_by_path : & HashMap < PathBuf , UnwindData > ,
80101 pid_unwind_data_mappings_by_pid : HashMap < i32 , Vec < UnwindDataPidMappingWithFullPath > > ,
102+ path_to_key : & mut HashMap < PathBuf , String > ,
81103) -> HashMap < i32 , Vec < UnwindDataPidMapping > > {
82104 debug ! (
83105 "Saving unwind data ({} unique entries)" ,
84106 unwind_data_by_path. len( )
85107 ) ;
86108
87- let path_to_key = build_path_to_key_map ( unwind_data_by_path. keys ( ) . map ( String :: as_str) ) ;
109+ // Pre-register all paths so the parallel section can use immutable borrows
110+ for path in unwind_data_by_path. keys ( ) {
111+ get_or_insert_key ( path_to_key, path) ;
112+ }
88113
89114 unwind_data_by_path. par_iter ( ) . for_each ( |( path, entry) | {
90- let key = & path_to_key[ path. as_str ( ) ] ;
115+ let key = & path_to_key[ path] ;
91116 entry. save_to ( profile_folder, key) . unwrap ( ) ;
92117 } ) ;
93118
@@ -97,7 +122,7 @@ pub fn save_unwind_data(
97122 let converted = mappings
98123 . into_iter ( )
99124 . map ( |m| UnwindDataPidMapping {
100- unwind_data_key : path_to_key[ m. path . as_str ( ) ] . clone ( ) ,
125+ unwind_data_key : path_to_key[ & m. path ] . clone ( ) ,
101126 timestamp : m. timestamp ,
102127 avma_range : m. avma_range ,
103128 base_avma : m. base_avma ,
@@ -173,18 +198,3 @@ fn convert_pid_mappings<T, K: Ord>(
173198 } )
174199 . collect ( )
175200}
176-
177- /// Build a `path_string → semantic_key` map from an iterator of path-like items.
178- fn build_path_to_key_map < I , S > ( paths : I ) -> HashMap < String , String >
179- where
180- I : Iterator < Item = S > ,
181- S : AsRef < str > ,
182- {
183- paths
184- . map ( |p| {
185- let s = p. as_ref ( ) . to_owned ( ) ;
186- let key = naming:: path_to_semantic_key ( & s) ;
187- ( s, key)
188- } )
189- . collect ( )
190- }
0 commit comments