@@ -694,6 +694,57 @@ static VALUE Memory_Profiler_Capture_aref(VALUE self, VALUE klass) {
694694 return Qnil ;
695695}
696696
697+ // Struct to accumulate statistics during iteration
698+ struct Memory_Profiler_Allocations_Statistics {
699+ size_t total_tracked_objects ;
700+ VALUE per_class_counts ;
701+ };
702+
703+ // Iterator callback to count object_states per class
704+ static int Memory_Profiler_Capture_count_object_states (st_data_t key , st_data_t value , st_data_t argument ) {
705+ struct Memory_Profiler_Allocations_Statistics * statistics = (struct Memory_Profiler_Allocations_Statistics * )argument ;
706+ VALUE klass = (VALUE )key ;
707+ VALUE allocations = (VALUE )value ;
708+ struct Memory_Profiler_Capture_Allocations * record = Memory_Profiler_Allocations_get (allocations );
709+
710+ size_t object_states_count = record -> object_states ? record -> object_states -> num_entries : 0 ;
711+ statistics -> total_tracked_objects += object_states_count ;
712+
713+ rb_hash_aset (statistics -> per_class_counts , klass , SIZET2NUM (object_states_count ));
714+ return ST_CONTINUE ;
715+ }
716+
717+ // Get internal statistics for debugging
718+ // Returns hash with internal state sizes
719+ static VALUE Memory_Profiler_Capture_statistics (VALUE self ) {
720+ struct Memory_Profiler_Capture * capture ;
721+ TypedData_Get_Struct (self , struct Memory_Profiler_Capture , & Memory_Profiler_Capture_type , capture );
722+
723+ VALUE statistics = rb_hash_new ();
724+
725+ // Tracked classes count
726+ rb_hash_aset (statistics , ID2SYM (rb_intern ("tracked_classes_count" )), SIZET2NUM (capture -> tracked_classes -> num_entries ));
727+
728+ // Queue sizes
729+ rb_hash_aset (statistics , ID2SYM (rb_intern ("newobj_queue_size" )), SIZET2NUM (capture -> newobj_queue .count ));
730+ rb_hash_aset (statistics , ID2SYM (rb_intern ("newobj_queue_capacity" )), SIZET2NUM (capture -> newobj_queue .capacity ));
731+ rb_hash_aset (statistics , ID2SYM (rb_intern ("freeobj_queue_size" )), SIZET2NUM (capture -> freeobj_queue .count ));
732+ rb_hash_aset (statistics , ID2SYM (rb_intern ("freeobj_queue_capacity" )), SIZET2NUM (capture -> freeobj_queue .capacity ));
733+
734+ // Count object_states entries for each tracked class
735+ struct Memory_Profiler_Allocations_Statistics allocations_statistics = {
736+ .total_tracked_objects = 0 ,
737+ .per_class_counts = rb_hash_new ()
738+ };
739+
740+ st_foreach (capture -> tracked_classes , Memory_Profiler_Capture_count_object_states , (st_data_t )& allocations_statistics );
741+
742+ rb_hash_aset (statistics , ID2SYM (rb_intern ("total_tracked_objects" )), SIZET2NUM (allocations_statistics .total_tracked_objects ));
743+ rb_hash_aset (statistics , ID2SYM (rb_intern ("tracked_objects_per_class" )), allocations_statistics .per_class_counts );
744+
745+ return statistics ;
746+ }
747+
697748void Init_Memory_Profiler_Capture (VALUE Memory_Profiler )
698749{
699750 // Initialize event symbols
@@ -715,6 +766,7 @@ void Init_Memory_Profiler_Capture(VALUE Memory_Profiler)
715766 rb_define_method (Memory_Profiler_Capture , "each" , Memory_Profiler_Capture_each , 0 );
716767 rb_define_method (Memory_Profiler_Capture , "[]" , Memory_Profiler_Capture_aref , 1 );
717768 rb_define_method (Memory_Profiler_Capture , "clear" , Memory_Profiler_Capture_clear , 0 );
769+ rb_define_method (Memory_Profiler_Capture , "statistics" , Memory_Profiler_Capture_statistics , 0 );
718770
719771 // Initialize Allocations class
720772 Init_Memory_Profiler_Allocations (Memory_Profiler );
0 commit comments