#include #include static VALUE rb_mPlainApm = Qnil; static VALUE rb_mObjTracing = Qnil; static __thread uint64_t allocated_objects = 0; #ifdef OBJECT_TRACING_ENABLED static int object_tracing_active = 0; static void track_thread_allocated_objects(VALUE tpval, void *data) { allocated_objects++; } #endif static VALUE total_thread_allocated_objects(VALUE self) { return ULL2NUM(allocated_objects); } void Init_object_tracing(void) { rb_mPlainApm = rb_define_module("PlainApm"); rb_gc_register_address(&rb_mPlainApm); rb_mObjTracing = rb_define_module_under(rb_mPlainApm, "ObjectTracing"); rb_gc_register_address(&rb_mObjTracing); rb_define_singleton_method(rb_mObjTracing, "total_thread_allocated_objects", total_thread_allocated_objects, 0); #ifdef OBJECT_TRACING_ENABLED /* Ensure the tracepoint is attached only once. */ if (object_tracing_active) { return; } object_tracing_active = 1; /* Object allocation tracing is impacted by these bugs: * * https://bugs.ruby-lang.org/issues/19112 in Rubies 3.x.x * https://bugs.ruby-lang.org/issues/18464 in Rubies 3.0, 3.1, and 3.2 * * According to * * https://www.ruby-lang.org/en/downloads/branches/ * * 3.0 goes out of maintenance mid 2024. The latter bug was backported to the * other branches. * * For the former, there's https://github.com/ruby/ruby/pull/7184 open, * unmerged as of Dec 2023. * */ VALUE tpval = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, track_thread_allocated_objects, NULL); rb_tracepoint_enable(tpval); #endif }