@@ -209,6 +209,47 @@ pub(crate) struct StackFrame {
209
209
pub ( crate ) calls_x2 : u32 ,
210
210
}
211
211
212
+ impl StackFrame {
213
+ fn merge_callees < ' a > (
214
+ frames : & ' a [ StackFrameWithContext < ' a > ] ,
215
+ strings : & mut StringIndex ,
216
+ ) -> SmallMap < StringId , StackFrame > {
217
+ let mut group_by_callee: SmallMap < & str , Vec < StackFrameWithContext > > = SmallMap :: new ( ) ;
218
+ for frame in frames {
219
+ for ( name, callee) in frame. callees ( ) {
220
+ group_by_callee
221
+ . entry ( name)
222
+ . or_insert_with ( Vec :: new)
223
+ . push ( callee) ;
224
+ }
225
+ }
226
+ group_by_callee
227
+ . into_iter ( )
228
+ . map ( |( name, frames) | {
229
+ let name = strings. index ( name) ;
230
+ ( name, StackFrame :: merge ( frames, strings) )
231
+ } )
232
+ . collect ( )
233
+ }
234
+
235
+ fn merge < ' a > (
236
+ frames : impl IntoIterator < Item = StackFrameWithContext < ' a > > ,
237
+ strings : & mut StringIndex ,
238
+ ) -> StackFrame {
239
+ let frames = Vec :: from_iter ( frames) ;
240
+ let callees = StackFrame :: merge_callees ( & frames, strings) ;
241
+ let allocs = HeapSummary :: merge ( frames. iter ( ) . map ( |f| & f. frame . allocs ) ) ;
242
+ let time_x2 = frames. iter ( ) . map ( |f| f. frame . time_x2 ) . sum ( ) ;
243
+ let calls_x2 = frames. iter ( ) . map ( |f| f. frame . calls_x2 ) . sum ( ) ;
244
+ StackFrame {
245
+ callees,
246
+ allocs,
247
+ time_x2,
248
+ calls_x2,
249
+ }
250
+ }
251
+ }
252
+
212
253
struct StackFrameWithContext < ' c > {
213
254
frame : & ' c StackFrame ,
214
255
strings : & ' c StringIndex ,
@@ -292,6 +333,25 @@ impl AggregateHeapProfileInfo {
292
333
}
293
334
}
294
335
336
+ #[ allow( dead_code) ] // TODO: used later.
337
+ fn merge < ' a > (
338
+ profiles : impl IntoIterator < Item = & ' a AggregateHeapProfileInfo > ,
339
+ ) -> AggregateHeapProfileInfo {
340
+ let mut strings = StringIndex :: default ( ) ;
341
+ let totals_id = strings. index ( Self :: TOTALS_STR ) ;
342
+ let root_id = strings. index ( Self :: ROOT_STR ) ;
343
+ let blank_id = strings. index ( Self :: BLANK_STR ) ;
344
+ let roots = profiles. into_iter ( ) . map ( |p| p. root ( ) ) ;
345
+ let root = StackFrame :: merge ( roots, & mut strings) ;
346
+ AggregateHeapProfileInfo {
347
+ strings,
348
+ root,
349
+ totals_id,
350
+ root_id,
351
+ blank_id,
352
+ }
353
+ }
354
+
295
355
/// Write this out recursively to a file.
296
356
pub ( crate ) fn gen_flame_graph ( & self ) -> String {
297
357
let mut writer = FlameGraphWriter :: new ( ) ;
@@ -312,6 +372,7 @@ mod tests {
312
372
use crate :: values:: layout:: heap:: heap_type:: HeapKind ;
313
373
use crate :: values:: layout:: heap:: profile:: aggregated:: AggregateHeapProfileInfo ;
314
374
use crate :: values:: layout:: heap:: profile:: aggregated:: StackFrame ;
375
+ use crate :: values:: layout:: heap:: profile:: summary:: HeapSummaryByFunction ;
315
376
use crate :: values:: Freezer ;
316
377
use crate :: values:: FrozenHeap ;
317
378
use crate :: values:: Heap ;
@@ -372,4 +433,25 @@ mod tests {
372
433
) ;
373
434
assert_eq ! ( 2 , total_alloc_count( & stacks. root) ) ;
374
435
}
436
+
437
+ #[ test]
438
+ fn test_merge ( ) {
439
+ fn make ( ) -> AggregateHeapProfileInfo {
440
+ let heap = Heap :: new ( ) ;
441
+ heap. record_call_enter ( const_frozen_string ! ( "xx" ) . to_value ( ) ) ;
442
+ let s = heap. alloc_str ( "abc" ) ;
443
+ heap. record_call_exit ( ) ;
444
+ let freezer = Freezer :: new ( FrozenHeap :: new ( ) ) ;
445
+ freezer. freeze ( s. to_value ( ) ) . unwrap ( ) ;
446
+
447
+ AggregateHeapProfileInfo :: collect ( & heap, Some ( HeapKind :: Frozen ) )
448
+ }
449
+
450
+ let merge = AggregateHeapProfileInfo :: merge ( [ & make ( ) , & make ( ) , & make ( ) ] ) ;
451
+ let summary = HeapSummaryByFunction :: init ( & merge) ;
452
+ assert_eq ! ( 1 , summary. info( ) . len( ) ) ;
453
+ let ( xx_id, xx_info) = summary. info ( ) [ 0 ] ;
454
+ assert_eq ! ( "xx" , merge. strings. get( xx_id) ) ;
455
+ assert_eq ! ( 3 , xx_info. alloc. get( "string" ) . unwrap( ) . count) ;
456
+ }
375
457
}
0 commit comments