@@ -59,6 +59,8 @@ static VALUE rb_mVernierMarkerType;
59
59
static VALUE rb_cVernierCollector;
60
60
static VALUE rb_cStackTable;
61
61
62
+ static VALUE sym_state, sym_gc_by;
63
+
62
64
static const char *gvl_event_name (rb_event_flag_t event) {
63
65
switch (event) {
64
66
case RUBY_INTERNAL_THREAD_EVENT_STARTED:
@@ -796,6 +798,12 @@ static native_thread_id_t get_native_thread_id() {
796
798
#endif
797
799
}
798
800
801
+ union MarkerInfo {
802
+ struct {
803
+ VALUE gc_by;
804
+ VALUE gc_state;
805
+ } gc_data;
806
+ };
799
807
800
808
class Marker {
801
809
public:
@@ -833,8 +841,10 @@ class Marker {
833
841
// native_thread_id_t thread_id;
834
842
int stack_index = -1 ;
835
843
844
+ MarkerInfo extra_info;
845
+
836
846
VALUE to_array () {
837
- VALUE record[6 ] = {0 };
847
+ VALUE record[7 ] = {0 };
838
848
record[0 ] = Qnil; // FIXME
839
849
record[1 ] = INT2NUM (type);
840
850
record[2 ] = INT2NUM (phase);
@@ -848,7 +858,14 @@ class Marker {
848
858
}
849
859
record[5 ] = stack_index == -1 ? Qnil : INT2NUM (stack_index);
850
860
851
- return rb_ary_new_from_values (6 , record);
861
+ if (type == Marker::MARKER_GC_PAUSE) {
862
+ VALUE hash = rb_hash_new ();
863
+ record[6 ] = hash;
864
+
865
+ rb_hash_aset (hash, sym_gc_by, extra_info.gc_data .gc_by );
866
+ rb_hash_aset (hash, sym_state, extra_info.gc_data .gc_state );
867
+ }
868
+ return rb_ary_new_from_values (7 , record);
852
869
}
853
870
};
854
871
@@ -863,7 +880,7 @@ class MarkerTable {
863
880
list.push_back ({ type, Marker::INTERVAL, from, to, stack_index });
864
881
}
865
882
866
- void record (Marker::Type type, int stack_index = -1 ) {
883
+ void record (Marker::Type type, int stack_index = -1 , MarkerInfo extra_info = {} ) {
867
884
const std::lock_guard<std::mutex> lock (mutex);
868
885
869
886
list.push_back ({ type, Marker::INSTANT, TimeStamp::Now (), TimeStamp (), stack_index });
@@ -874,12 +891,34 @@ class GCMarkerTable: public MarkerTable {
874
891
TimeStamp last_gc_entry;
875
892
876
893
public:
894
+ void record_gc_start () {
895
+ record (Marker::Type::MARKER_GC_START);
896
+ }
897
+
877
898
void record_gc_entered () {
878
899
last_gc_entry = TimeStamp::Now ();
879
900
}
880
901
881
902
void record_gc_leave () {
882
- list.push_back ({ Marker::MARKER_GC_PAUSE, Marker::INTERVAL, last_gc_entry, TimeStamp::Now (), -1 });
903
+ VALUE gc_state = rb_gc_latest_gc_info (sym_state);
904
+ VALUE gc_by = rb_gc_latest_gc_info (sym_gc_by);
905
+ union MarkerInfo info = {
906
+ .gc_data = {
907
+ .gc_by = gc_by,
908
+ .gc_state = gc_state
909
+ }
910
+ };
911
+ list.push_back ({ Marker::MARKER_GC_PAUSE, Marker::INTERVAL, last_gc_entry, TimeStamp::Now (), -1 , info });
912
+ }
913
+
914
+ void record_gc_end_mark () {
915
+ record_gc_leave ();
916
+ record (Marker::Type::MARKER_GC_END_MARK);
917
+ record_gc_entered ();
918
+ }
919
+
920
+ void record_gc_end_sweep () {
921
+ record (Marker::Type::MARKER_GC_END_SWEEP);
883
922
}
884
923
};
885
924
@@ -1701,13 +1740,13 @@ class TimeCollector : public BaseCollector {
1701
1740
1702
1741
switch (event) {
1703
1742
case RUBY_INTERNAL_EVENT_GC_START:
1704
- collector->gc_markers .record (Marker::Type::MARKER_GC_START );
1743
+ collector->gc_markers .record_gc_start ( );
1705
1744
break ;
1706
1745
case RUBY_INTERNAL_EVENT_GC_END_MARK:
1707
- collector->gc_markers .record (Marker::Type::MARKER_GC_END_MARK );
1746
+ collector->gc_markers .record_gc_end_mark ( );
1708
1747
break ;
1709
1748
case RUBY_INTERNAL_EVENT_GC_END_SWEEP:
1710
- collector->gc_markers .record (Marker::Type::MARKER_GC_END_SWEEP );
1749
+ collector->gc_markers .record_gc_end_sweep ( );
1711
1750
break ;
1712
1751
case RUBY_INTERNAL_EVENT_GC_ENTER:
1713
1752
collector->gc_markers .record_gc_entered ();
@@ -1998,6 +2037,10 @@ Init_consts(VALUE rb_mVernierMarkerPhase) {
1998
2037
extern " C" void
1999
2038
Init_vernier (void )
2000
2039
{
2040
+ sym_state = sym (" state" );
2041
+ sym_gc_by = sym (" gc_by" );
2042
+ rb_gc_latest_gc_info (sym_state); // HACK: needs to be warmed so that it can be called during GC
2043
+
2001
2044
rb_mVernier = rb_define_module (" Vernier" );
2002
2045
rb_cVernierResult = rb_define_class_under (rb_mVernier, " Result" , rb_cObject);
2003
2046
VALUE rb_mVernierMarker = rb_define_module_under (rb_mVernier, " Marker" );
0 commit comments