@@ -31,44 +31,44 @@ fn get_or_insert_key(path_to_key: &mut HashMap<PathBuf, String>, path: &Path) ->
3131 key
3232}
3333
34- /// Save all artifacts (symbols, debug info, unwind data) from mounted modules and JIT data .
35- pub fn save_artifacts (
36- profile_folder : & Path ,
34+ /// Pre-register all paths from the mounted modules map .
35+ fn register_paths (
36+ path_to_key : & mut HashMap < PathBuf , String > ,
3737 mounted_modules_by_path : & HashMap < PathBuf , MountedModule > ,
38- jit_unwind_data_by_pid : & HashMap < pid_t , Vec < ( UnwindData , ProcessUnwindData ) > > ,
39- ) -> SavedArtifacts {
40- let mut path_to_key = HashMap :: < PathBuf , String > :: new ( ) ;
38+ ) {
39+ for path in mounted_modules_by_path. keys ( ) {
40+ get_or_insert_key ( path_to_key, path) ;
41+ }
42+ }
4143
42- // --- 1. Save symbol files and build per-pid symbol mappings ---
44+ /// Save deduplicated symbol files to disk and build per-pid mappings.
45+ fn save_symbols (
46+ profile_folder : & Path ,
47+ mounted_modules_by_path : & HashMap < PathBuf , MountedModule > ,
48+ path_to_key : & HashMap < PathBuf , String > ,
49+ ) -> HashMap < pid_t , Vec < ProcessModuleLoadBias > > {
4350 let symbols_count = mounted_modules_by_path
4451 . values ( )
4552 . filter ( |m| m. module_symbols . is_some ( ) )
4653 . count ( ) ;
4754 debug ! ( "Saving symbols ({symbols_count} unique entries)" ) ;
4855
49- // Pre-register all paths
50- for path in mounted_modules_by_path. keys ( ) {
51- get_or_insert_key ( & mut path_to_key, path) ;
52- }
53-
54- // Save symbol files in parallel
5556 mounted_modules_by_path. par_iter ( ) . for_each ( |( path, m) | {
5657 if let Some ( ref symbols) = m. module_symbols {
5758 let key = & path_to_key[ path] ;
5859 symbols. save_to_keyed_file ( profile_folder, key) . unwrap ( ) ;
5960 }
6061 } ) ;
6162
62- // Build per-pid symbol mappings
63- let mut symbol_pid_mappings_by_pid: HashMap < pid_t , Vec < ProcessModuleLoadBias > > = HashMap :: new ( ) ;
63+ let mut mappings_by_pid: HashMap < pid_t , Vec < ProcessModuleLoadBias > > = HashMap :: new ( ) ;
6464 for ( path, m) in mounted_modules_by_path {
6565 if m. module_symbols . is_none ( ) {
6666 continue ;
6767 }
6868 let key = & path_to_key[ path] ;
6969 for ( & pid, pm) in & m. process_mounted_module {
7070 if let Some ( load_bias) = pm. symbols_load_bias {
71- symbol_pid_mappings_by_pid
71+ mappings_by_pid
7272 . entry ( pid)
7373 . or_default ( )
7474 . push ( ProcessModuleLoadBias {
@@ -78,19 +78,26 @@ pub fn save_artifacts(
7878 }
7979 }
8080 }
81- // Sort each pid's mappings by key for deterministic output
82- for mappings in symbol_pid_mappings_by_pid. values_mut ( ) {
81+ for mappings in mappings_by_pid. values_mut ( ) {
8382 mappings. sort_by ( |a, b| a. perf_map_key . cmp ( & b. perf_map_key ) ) ;
8483 }
84+ mappings_by_pid
85+ }
8586
86- // --- 2. Compute debug info and build per-pid debug info mappings ---
87+ /// Compute debug info from symbols and build per-pid debug info mappings.
88+ fn save_debug_info (
89+ mounted_modules_by_path : & HashMap < PathBuf , MountedModule > ,
90+ path_to_key : & mut HashMap < PathBuf , String > ,
91+ ) -> (
92+ HashMap < String , ModuleDebugInfo > ,
93+ HashMap < pid_t , Vec < DebugInfoPidMapping > > ,
94+ ) {
8795 debug ! ( "Saving debug_info" ) ;
8896
8997 let debug_info_by_elf_path = debug_info_by_path ( mounted_modules_by_path) ;
9098
91- // Pre-register debug info paths
9299 for path in debug_info_by_elf_path. keys ( ) {
93- get_or_insert_key ( & mut path_to_key, path) ;
100+ get_or_insert_key ( path_to_key, path) ;
94101 }
95102
96103 let debug_info: HashMap < String , ModuleDebugInfo > = debug_info_by_elf_path
@@ -101,8 +108,7 @@ pub fn save_artifacts(
101108 } )
102109 . collect ( ) ;
103110
104- let mut debug_info_pid_mappings_by_pid: HashMap < pid_t , Vec < DebugInfoPidMapping > > =
105- HashMap :: new ( ) ;
111+ let mut mappings_by_pid: HashMap < pid_t , Vec < DebugInfoPidMapping > > = HashMap :: new ( ) ;
106112 for ( path, m) in mounted_modules_by_path {
107113 if m. module_symbols . is_none ( ) {
108114 continue ;
@@ -112,7 +118,7 @@ pub fn save_artifacts(
112118 } ;
113119 for ( & pid, pm) in & m. process_mounted_module {
114120 if let Some ( load_bias) = pm. symbols_load_bias {
115- debug_info_pid_mappings_by_pid
121+ mappings_by_pid
116122 . entry ( pid)
117123 . or_default ( )
118124 . push ( DebugInfoPidMapping {
@@ -122,41 +128,43 @@ pub fn save_artifacts(
122128 }
123129 }
124130 }
125- for mappings in debug_info_pid_mappings_by_pid . values_mut ( ) {
131+ for mappings in mappings_by_pid . values_mut ( ) {
126132 mappings. sort_by ( |a, b| a. debug_info_key . cmp ( & b. debug_info_key ) ) ;
127133 }
128134
129- // --- 3. Save unwind data files and build per-pid unwind data mappings ---
135+ ( debug_info, mappings_by_pid)
136+ }
137+
138+ /// Save deduplicated unwind data files to disk and build per-pid mappings,
139+ /// including JIT unwind data.
140+ fn save_unwind_data (
141+ profile_folder : & Path ,
142+ mounted_modules_by_path : & HashMap < PathBuf , MountedModule > ,
143+ jit_unwind_data_by_pid : & HashMap < pid_t , Vec < ( UnwindData , ProcessUnwindData ) > > ,
144+ path_to_key : & mut HashMap < PathBuf , String > ,
145+ ) -> HashMap < pid_t , Vec < UnwindDataPidMapping > > {
130146 let unwind_data_count = mounted_modules_by_path
131147 . values ( )
132148 . filter ( |m| m. unwind_data . is_some ( ) )
133149 . count ( ) ;
134150 debug ! ( "Saving unwind data ({unwind_data_count} unique entries)" ) ;
135151
136- // Pre-register all paths for unwind data
137- for path in mounted_modules_by_path. keys ( ) {
138- get_or_insert_key ( & mut path_to_key, path) ;
139- }
140-
141- // Save unwind data files in parallel
142152 mounted_modules_by_path. par_iter ( ) . for_each ( |( path, m) | {
143153 if let Some ( ref unwind_data) = m. unwind_data {
144154 let key = & path_to_key[ path] ;
145155 unwind_data. save_to ( profile_folder, key) . unwrap ( ) ;
146156 }
147157 } ) ;
148158
149- // Build per-pid unwind data mappings from mounted modules
150- let mut unwind_data_pid_mappings_by_pid: HashMap < pid_t , Vec < UnwindDataPidMapping > > =
151- HashMap :: new ( ) ;
159+ let mut mappings_by_pid: HashMap < pid_t , Vec < UnwindDataPidMapping > > = HashMap :: new ( ) ;
152160 for ( path, m) in mounted_modules_by_path {
153161 if m. unwind_data . is_none ( ) {
154162 continue ;
155163 }
156164 let key = & path_to_key[ path] ;
157165 for ( & pid, pm) in & m. process_mounted_module {
158166 if let Some ( ref pud) = pm. process_unwind_data {
159- unwind_data_pid_mappings_by_pid
167+ mappings_by_pid
160168 . entry ( pid)
161169 . or_default ( )
162170 . push ( UnwindDataPidMapping {
@@ -173,9 +181,9 @@ pub fn save_artifacts(
173181 for ( & pid, jit_entries) in jit_unwind_data_by_pid {
174182 for ( unwind_data, process_unwind_data) in jit_entries {
175183 let jit_path = PathBuf :: from ( & unwind_data. path ) ;
176- let key = get_or_insert_key ( & mut path_to_key, & jit_path) ;
184+ let key = get_or_insert_key ( path_to_key, & jit_path) ;
177185 unwind_data. save_to ( profile_folder, & key) . unwrap ( ) ;
178- unwind_data_pid_mappings_by_pid
186+ mappings_by_pid
179187 . entry ( pid)
180188 . or_default ( )
181189 . push ( UnwindDataPidMapping {
@@ -187,27 +195,11 @@ pub fn save_artifacts(
187195 }
188196 }
189197
190- for mappings in unwind_data_pid_mappings_by_pid . values_mut ( ) {
198+ for mappings in mappings_by_pid . values_mut ( ) {
191199 mappings. sort_by ( |a, b| a. unwind_data_key . cmp ( & b. unwind_data_key ) ) ;
192200 }
193201
194- // --- 4. Collect ignored modules ---
195- let ignored_modules = collect_ignored_modules ( mounted_modules_by_path) ;
196-
197- // --- 5. Build key_to_path (inverted) ---
198- let key_to_path = path_to_key
199- . into_iter ( )
200- . map ( |( path, key) | ( key, path) )
201- . collect ( ) ;
202-
203- SavedArtifacts {
204- symbol_pid_mappings_by_pid,
205- debug_info,
206- debug_info_pid_mappings_by_pid,
207- unwind_data_pid_mappings_by_pid,
208- ignored_modules,
209- key_to_path,
210- }
202+ mappings_by_pid
211203}
212204
213205/// Collect ignored modules by finding known-ignored and python modules in the mounted modules.
@@ -221,7 +213,9 @@ fn collect_ignored_modules(
221213 for ( path, m) in mounted_modules_by_path {
222214 let path_str = path. to_string_lossy ( ) ;
223215
224- let is_ignored = ignore_paths. iter ( ) . any ( |ip| path_str. as_ref ( ) == ip. as_str ( ) ) ;
216+ let is_ignored = ignore_paths
217+ . iter ( )
218+ . any ( |ip| path_str. as_ref ( ) == ip. as_str ( ) ) ;
225219 let is_python = path
226220 . file_name ( )
227221 . map ( |name| name. to_string_lossy ( ) . starts_with ( "python" ) )
@@ -231,7 +225,6 @@ fn collect_ignored_modules(
231225 continue ;
232226 }
233227
234- // Collect address range across all pids for this module
235228 for pm in m. process_mounted_module . values ( ) {
236229 if let Some ( ref pud) = pm. process_unwind_data {
237230 to_ignore. push ( (
@@ -245,3 +238,43 @@ fn collect_ignored_modules(
245238
246239 to_ignore
247240}
241+
242+ /// Save all artifacts (symbols, debug info, unwind data) from mounted modules and JIT data.
243+ pub fn save_artifacts (
244+ profile_folder : & Path ,
245+ mounted_modules_by_path : & HashMap < PathBuf , MountedModule > ,
246+ jit_unwind_data_by_pid : & HashMap < pid_t , Vec < ( UnwindData , ProcessUnwindData ) > > ,
247+ ) -> SavedArtifacts {
248+ let mut path_to_key = HashMap :: < PathBuf , String > :: new ( ) ;
249+
250+ register_paths ( & mut path_to_key, mounted_modules_by_path) ;
251+
252+ let symbol_pid_mappings_by_pid =
253+ save_symbols ( profile_folder, mounted_modules_by_path, & path_to_key) ;
254+
255+ let ( debug_info, debug_info_pid_mappings_by_pid) =
256+ save_debug_info ( mounted_modules_by_path, & mut path_to_key) ;
257+
258+ let unwind_data_pid_mappings_by_pid = save_unwind_data (
259+ profile_folder,
260+ mounted_modules_by_path,
261+ jit_unwind_data_by_pid,
262+ & mut path_to_key,
263+ ) ;
264+
265+ let ignored_modules = collect_ignored_modules ( mounted_modules_by_path) ;
266+
267+ let key_to_path = path_to_key
268+ . into_iter ( )
269+ . map ( |( path, key) | ( key, path) )
270+ . collect ( ) ;
271+
272+ SavedArtifacts {
273+ symbol_pid_mappings_by_pid,
274+ debug_info,
275+ debug_info_pid_mappings_by_pid,
276+ unwind_data_pid_mappings_by_pid,
277+ ignored_modules,
278+ key_to_path,
279+ }
280+ }
0 commit comments