@@ -231,13 +231,11 @@ pub enum ProfilerMessage {
231231 Wake ,
232232}
233233
234- /// A complete sample stored for live heap tracking. Contains everything needed
235- /// to send an identical deallocation sample (with negated heap-live-* values).
236- #[ derive( Clone , Debug ) ]
237234/// Tracked allocation for batched heap-live sample emission.
238235/// Unlike the .NET profiler which tracks CLR objects via weak handles,
239236/// we track raw allocation pointers. Samples are emitted in batches
240237/// at profile export time, not on each allocation/free.
238+ #[ derive( Clone , Debug ) ]
241239pub struct LiveHeapSample {
242240 /// The profile index (sample_types + tags) for adding to correct profile
243241 pub key : ProfileIndex ,
@@ -318,16 +316,17 @@ impl TimeCollector {
318316 let tracked = entry. value ( ) ;
319317
320318 // Build sample_values with only heap-live-samples and heap-live-size set
321- let mut sample_values = vec ! [ 0i64 ; tracked. key. sample_types. len( ) ] ;
322- for ( i, st) in tracked. key . sample_types . iter ( ) . enumerate ( ) {
323- if st. r#type == "heap-live-samples" {
324- sample_values[ i] = 1 ;
325- } else if st. r#type == "heap-live-size" {
326- sample_values[ i] = tracked. allocation_size ;
327- }
328- }
319+ let sample_values: Vec < i64 > = tracked
320+ . key
321+ . sample_types
322+ . iter ( )
323+ . map ( |st| match st. r#type {
324+ "heap-live-samples" => 1 ,
325+ "heap-live-size" => tracked. allocation_size ,
326+ _ => 0 ,
327+ } )
328+ . collect ( ) ;
329329
330- // Create the sample message
331330 let message = SampleMessage {
332331 key : tracked. key . clone ( ) ,
333332 value : SampleData {
@@ -1160,14 +1159,12 @@ impl Profiler {
11601159
11611160 // Track allocation for heap live profiling if enabled.
11621161 // Samples will be emitted in batch at profile export time.
1163- // Fetch sample_types and tags once, reuse for both tracking and sending.
1164- let sample_types = self . sample_types_filter . sample_types ( ) ;
1165- let tags = TAGS . with_borrow ( Arc :: clone) ;
1166- let key = ProfileIndex { sample_types, tags } ;
1167-
11681162 if self . is_heap_live_enabled ( ) {
11691163 let tracked = LiveHeapSample {
1170- key : key. clone ( ) ,
1164+ key : ProfileIndex {
1165+ sample_types : self . sample_types_filter . sample_types ( ) ,
1166+ tags : TAGS . with_borrow ( Arc :: clone) ,
1167+ } ,
11711168 frames : frames. clone ( ) ,
11721169 labels : labels. clone ( ) ,
11731170 allocation_size : alloc_size,
@@ -1181,16 +1178,7 @@ impl Profiler {
11811178 }
11821179 }
11831180
1184- let sample_values = self . sample_types_filter . filter ( sample_values) ;
1185- let message = SampleMessage {
1186- key,
1187- value : SampleData {
1188- frames,
1189- labels,
1190- sample_values,
1191- timestamp,
1192- } ,
1193- } ;
1181+ let message = self . prepare_sample_message ( frames, sample_values, labels, timestamp) ;
11941182
11951183 match self . message_sender . try_send ( ProfilerMessage :: Sample ( message) ) {
11961184 Ok ( _) => trace ! (
@@ -1210,14 +1198,19 @@ impl Profiler {
12101198 /// Called when memory is freed. Removes the allocation from tracking. The next profile export
12111199 /// will not include this allocation in the heap-live samples.
12121200 pub fn free_allocation ( & self , ptr : * mut std:: ffi:: c_void ) {
1201+ // Bail out early if heap-live tracking is disabled to avoid DashMap lookup overhead
1202+ if !self . is_heap_live_enabled ( ) {
1203+ return ;
1204+ }
1205+
12131206 if let Some ( sample) = self . untrack_allocation ( ptr as usize ) {
12141207 trace ! (
12151208 "Untracked freed allocation at {:#x} ({} bytes)" ,
12161209 ptr as usize ,
12171210 sample. allocation_size
12181211 ) ;
12191212 }
1220- // If not tracked, nothing to do (wasn't sampled or tracking disabled )
1213+ // If not tracked, nothing to do (wasn't sampled)
12211214 }
12221215
12231216 /// Collect a stack sample with exception.
0 commit comments