@@ -92,11 +92,16 @@ use crate::span::v04::Span;
9292use crate :: span:: vec_map:: VecMap ;
9393use crate :: span:: { SpanText , TraceData } ;
9494
95+ /// A stateful wrapper around a change buffer for processing and span reconstructions.
9596pub struct ChangeBufferState < T : TraceData > {
9697 change_buffer : ChangeBuffer ,
9798 spans : Vec < Option < Span < T > > > ,
9899 traces : SmallTraceMap < T :: Text > ,
99- /// String table indexed by sequential u32 IDs (O(1) lookup vs HashMap).
100+ /// Interned string table (O(1) lookup vs HashMap).
101+ ///
102+ /// Note: currently the string table never shrinks (it is never compacted). When entries are
103+ /// evicted (freeing the backing strings), a small amount of memory is leaked (to hold the
104+ /// `None` value).
100105 string_table : Vec < Option < T :: Text > > ,
101106 tracer_service : T :: Text ,
102107 tracer_language : T :: Text ,
@@ -175,10 +180,6 @@ where
175180 tracer_language : T :: Text ,
176181 pid : u32 ,
177182 ) -> Self {
178- eprintln ! (
179- "[libdatadog pipeline] experiment: baseline (commit: {})" ,
180- env!( "GIT_COMMIT" )
181- ) ;
182183 ChangeBufferState {
183184 change_buffer,
184185 spans : Vec :: with_capacity ( 256 ) ,
@@ -346,6 +347,11 @@ where
346347 let mut count = self . change_buffer . read :: < u64 > ( & mut index) ? as u32 ;
347348
348349 let mut cached_slot: u32 = u32:: MAX ;
350+ // We keep a bunch of cached internal pointers. They are safe to use as long as we don't
351+ // modify their parent vector and keep a unique borrow to `self` overall.
352+ //
353+ // Using mutable references instead would be better, but is not possible (or very hard)
354+ // given we iterate and nest calls to different submethods taking a `&mut self`.
349355 let mut cached_span_ptr: * mut Span < T > = std:: ptr:: null_mut ( ) ;
350356 let mut cached_deferred_meta: * mut VecMap < u32 , u32 > = std:: ptr:: null_mut ( ) ;
351357 let mut cached_deferred_metrics: * mut VecMap < u32 , f64 > = std:: ptr:: null_mut ( ) ;
@@ -407,11 +413,18 @@ where
407413 span
408414 } ;
409415
410- // SAFETY: span_ptr is valid — it was obtained from self.spans above
411- // or from the cache which was set in a previous iteration of the same loop.
412- // self.spans is not modified during this function (no inserts/removes).
416+ // SAFETY: span_ptr is valid for read and writes: it was obtained from self.spans above or
417+ // from the cache which was set in a previous iteration of the same loop. self.spans is not
418+ // modified during this function (no inserts/removes).
413419 let span = unsafe { & mut * span_ptr } ;
414420
421+ // SAFETY:
422+ //
423+ // - `cached_deferred_xxx`: they point to writable memory (derived from self), and we don't
424+ // modify, move nor drop the parent `deferred_xxx` vec, so the pointer should remain
425+ // valid.
426+ // - `xxx_unchecked`: we rely on the encoder side to write the correct arguments to an
427+ // opcode.
415428 match op. opcode {
416429 OpCode :: SetMetaAttr => {
417430 let key_id: u32 = self . get_num_arg ( index) ?;
@@ -501,6 +514,9 @@ where
501514 . ok_or ( ChangeBufferError :: StringNotFound ( num) )
502515 }
503516
517+ /// # Safety
518+ ///
519+ /// Caller must ensure `*index + size_of::<T::Tex>() <= self.change_buffer.len`.
504520 #[ inline( always) ]
505521 unsafe fn get_string_arg_unchecked ( & self , index : & mut usize ) -> T :: Text {
506522 let num: u32 = self . change_buffer . read_unchecked ( index) ;
@@ -514,12 +530,16 @@ where
514530 self . change_buffer . read ( index)
515531 }
516532
533+ /// # Safety
534+ ///
535+ /// Caller must ensure `*index + size_of::<U>() <= self.change_buffer.len`.
517536 #[ inline( always) ]
518537 unsafe fn get_num_arg_unchecked < U : Copy + FromBytes > ( & self , index : & mut usize ) -> U {
519- self . change_buffer . read_unchecked ( index)
538+ // Safety: this function's pre-condition
539+ unsafe { self . change_buffer . read_unchecked ( index) }
520540 }
521541
522- fn get_mut_span ( & mut self , slot : u32 ) -> Result < & mut Span < T > > {
542+ fn get_span_mut ( & mut self , slot : u32 ) -> Result < & mut Span < T > > {
523543 self . spans
524544 . get_mut ( slot as usize )
525545 . and_then ( |opt| opt. as_mut ( ) )
@@ -533,6 +553,7 @@ where
533553 . ok_or ( ChangeBufferError :: SpanNotFound ( slot as u64 ) )
534554 }
535555
556+ #[ inline]
536557 pub fn get_trace ( & self , id : & u128 ) -> Option < & Trace < T :: Text > > {
537558 self . traces . get ( id)
538559 }
@@ -627,12 +648,14 @@ where
627648 . ok_or ( ChangeBufferError :: SpanNotFound ( * slot as u64 ) )
628649 }
629650
651+ #[ inline]
630652 pub fn get_string ( & self , id : u32 ) -> Option < T :: Text > {
631653 self . string_table
632654 . get ( id as usize )
633655 . and_then ( |opt| opt. clone ( ) )
634656 }
635657
658+ #[ inline]
636659 pub fn set_default_meta ( & mut self , tags : Vec < ( T :: Text , T :: Text ) > ) {
637660 self . default_meta = tags;
638661 }
@@ -647,6 +670,7 @@ where
647670 let idx = slot as usize ;
648671 if idx < self . deferred_meta . len ( ) {
649672 let pairs: Vec < ( u32 , u32 ) > = self . deferred_meta [ idx] . drain ( ..) . collect ( ) ;
673+
650674 for ( key_id, val_id) in pairs {
651675 if let ( Some ( key) , Some ( val) ) = ( self . get_string ( key_id) , self . get_string ( val_id) ) {
652676 span. meta . insert ( key, val) ;
@@ -655,6 +679,7 @@ where
655679 }
656680 if idx < self . deferred_metrics . len ( ) {
657681 let pairs: Vec < ( u32 , f64 ) > = self . deferred_metrics [ idx] . drain ( ..) . collect ( ) ;
682+
658683 for ( key_id, val) in pairs {
659684 if let Some ( key) = self . get_string ( key_id) {
660685 span. metrics . insert ( key, val) ;
@@ -737,25 +762,25 @@ where
737762 }
738763 }
739764 OpCode :: SetServiceName => {
740- self . get_mut_span ( op. slot_index ) ?. service = self . get_string_arg ( index) ?;
765+ self . get_span_mut ( op. slot_index ) ?. service = self . get_string_arg ( index) ?;
741766 }
742767 OpCode :: SetResourceName => {
743- self . get_mut_span ( op. slot_index ) ?. resource = self . get_string_arg ( index) ?;
768+ self . get_span_mut ( op. slot_index ) ?. resource = self . get_string_arg ( index) ?;
744769 }
745770 OpCode :: SetError => {
746- self . get_mut_span ( op. slot_index ) ?. error = self . get_num_arg ( index) ?;
771+ self . get_span_mut ( op. slot_index ) ?. error = self . get_num_arg ( index) ?;
747772 }
748773 OpCode :: SetStart => {
749- self . get_mut_span ( op. slot_index ) ?. start = self . get_num_arg ( index) ?;
774+ self . get_span_mut ( op. slot_index ) ?. start = self . get_num_arg ( index) ?;
750775 }
751776 OpCode :: SetDuration => {
752- self . get_mut_span ( op. slot_index ) ?. duration = self . get_num_arg ( index) ?;
777+ self . get_span_mut ( op. slot_index ) ?. duration = self . get_num_arg ( index) ?;
753778 }
754779 OpCode :: SetType => {
755- self . get_mut_span ( op. slot_index ) ?. r#type = self . get_string_arg ( index) ?;
780+ self . get_span_mut ( op. slot_index ) ?. r#type = self . get_string_arg ( index) ?;
756781 }
757782 OpCode :: SetName => {
758- self . get_mut_span ( op. slot_index ) ?. name = self . get_string_arg ( index) ?;
783+ self . get_span_mut ( op. slot_index ) ?. name = self . get_string_arg ( index) ?;
759784 }
760785 OpCode :: SetTraceMetaAttr => {
761786 let name = self . get_string_arg ( index) ?;
0 commit comments