diff --git a/README b/README index b7658e7..9b14cdb 100644 --- a/README +++ b/README @@ -33,6 +33,10 @@ google-perftools for ruby code $ CPUPROFILE_OBJECTS=1 ruby my_app.rb + Profile method calls: + + $ CPUPROFILE_METHODS=1 ruby my_app.rb + === Reporting diff --git a/ext/perftools.c b/ext/perftools.c index 7313ac3..8f6f9a2 100644 --- a/ext/perftools.c +++ b/ext/perftools.c @@ -213,6 +213,8 @@ static VALUE Isend; static VALUE objprofiler_setup(); static VALUE objprofiler_teardown(); +static VALUE methprofiler_setup(); +static VALUE methprofiler_teardown(); /* CpuProfiler */ @@ -236,6 +238,7 @@ cpuprofiler_stop(VALUE self) bProfilerRunning = Qfalse; objprofiler_teardown(); + methprofiler_teardown(); ProfilerStop(); ProfilerFlush(); @@ -252,6 +255,8 @@ cpuprofiler_start(VALUE self, VALUE filename) if (getenv("CPUPROFILE_OBJECTS")) objprofiler_setup(); + else if (getenv("CPUPROFILE_METHODS")) + methprofiler_setup(); if (ProfilerStart(RSTRING_PTR(filename))) { bProfilerRunning = Qtrue; @@ -285,6 +290,7 @@ cpuprofiler_gc_mark() #include static VALUE bObjProfilerRunning; +static VALUE bMethProfilerRunning; #define NUM_ORIG_BYTES 2 struct { @@ -332,6 +338,35 @@ uc_get_ip(ucontext_t *uc) { return (char**)&uc->program_counter; } +static void +event_handler(rb_event_t event, NODE *node, VALUE self, ID id, VALUE klass) { + ProfilerRecord(0, NULL, NULL); +} + +static VALUE +methprofiler_setup() +{ + if (bMethProfilerRunning) + return Qtrue; + + rb_add_event_hook(event_handler, RUBY_EVENT_CALL); + + bMethProfilerRunning = Qtrue; + return Qtrue; +} + +static VALUE +methprofiler_teardown() +{ + if (!bMethProfilerRunning) + return Qfalse; + + rb_remove_event_hook(event_handler); + + bMethProfilerRunning = Qfalse; + return Qtrue; +} + static void trap_handler(int sig, siginfo_t *info, void *data) { int i; @@ -423,7 +458,7 @@ Init_perftools() I__send__ = rb_intern("__send__"); Isend = rb_intern("send"); - bObjProfilerRunning = bProfilerRunning = Qfalse; + bMethProfilerRunning = bObjProfilerRunning = bProfilerRunning = Qfalse; rb_define_singleton_method(cCpuProfiler, "running?", cpuprofiler_running_p, 0); rb_define_singleton_method(cCpuProfiler, "start", cpuprofiler_start, 1); @@ -437,6 +472,8 @@ Init_perftools() if (getenv("CPUPROFILE_OBJECTS")) { // want to profile objects objprofiler_setup(); + } else if (getenv("CPUPROFILE_METHODS")) { + methprofiler_setup(); } rb_set_end_proc(profiler_at_exit, 0); // make sure to cleanup before the VM shuts down diff --git a/patches/perftools-objects.patch b/patches/perftools-objects.patch index 290728d..3203857 100644 --- a/patches/perftools-objects.patch +++ b/patches/perftools-objects.patch @@ -12,7 +12,7 @@ index 619b980..2ecf2c0 100644 } void ProfileHandler::StartTimer() { -+ if (getenv("CPUPROFILE_OBJECTS")) return; ++ if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return; + struct itimerval timer; timer.it_interval.tv_sec = 0; @@ -21,7 +21,7 @@ index 619b980..2ecf2c0 100644 } void ProfileHandler::StopTimer() { -+ if (getenv("CPUPROFILE_OBJECTS")) return; ++ if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return; + struct itimerval timer; memset(&timer, 0, sizeof timer); @@ -29,7 +29,7 @@ index 619b980..2ecf2c0 100644 } bool ProfileHandler::IsTimerRunning() { -+ if (getenv("CPUPROFILE_OBJECTS")) return false; ++ if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return false; + struct itimerval current_timer; RAW_CHECK(0 == getitimer(realtime_ ? ITIMER_REAL : ITIMER_PROF, ¤t_timer), "getitimer"); @@ -38,7 +38,7 @@ index 619b980..2ecf2c0 100644 } void ProfileHandler::EnableHandler() { -+ if (getenv("CPUPROFILE_OBJECTS")) return; ++ if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return; + struct sigaction sa; sa.sa_sigaction = SignalHandler; @@ -47,7 +47,7 @@ index 619b980..2ecf2c0 100644 } void ProfileHandler::DisableHandler() { -+ if (getenv("CPUPROFILE_OBJECTS")) return; ++ if (getenv("CPUPROFILE_OBJECTS") || getenv("CPUPROFILE_METHODS")) return; + struct sigaction sa; sa.sa_handler = SIG_IGN;