From 329e57bced0a163bcf93288b2debae60d3514657 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 11 Jul 2023 16:49:57 -0700 Subject: [PATCH] Fix GC profiling timing We were recording GC profile timestamps inside the VM postponed job that flushes temporary information. The postponed job could be run much later than the sample was actually taken, so this commit records a timestamp in the signal handler when there is a GC event. It only records one time stamp, so if there are multiple GC events in a row, we have to assume that the total duration spent in GC starts from the first time stamp and extends until the timestamp of the next non-GC sample. In other words, we don't record a correct timestamp for each GC sample, only the first one. --- ext/stackprof/stackprof.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/stackprof/stackprof.c b/ext/stackprof/stackprof.c index 266109b..e7864b8 100644 --- a/ext/stackprof/stackprof.c +++ b/ext/stackprof/stackprof.c @@ -120,6 +120,8 @@ static struct { size_t unrecorded_gc_sweeping_samples; st_table *frames; + timestamp_t gc_start_timestamp; + VALUE fake_frame_names[TOTAL_FAKE_FRAMES]; VALUE empty_string; @@ -646,6 +648,7 @@ stackprof_buffer_sample(void) _stackprof.buffer_time.delta_usec = timestamp_delta; } +// Postponed job void stackprof_record_gc_samples(void) { @@ -653,8 +656,7 @@ stackprof_record_gc_samples(void) uint64_t start_timestamp = 0; size_t i; if (_stackprof.raw) { - struct timestamp_t t; - capture_timestamp(&t); + struct timestamp_t t = _stackprof.gc_start_timestamp; start_timestamp = timestamp_usec(&t); // We don't know when the GC samples were actually marked, so let's @@ -776,6 +778,10 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext) } else if (mode == sym_sweeping) { _stackprof.unrecorded_gc_sweeping_samples++; } + if(!_stackprof.unrecorded_gc_samples) { + // record start + capture_timestamp(&_stackprof.gc_start_timestamp); + } _stackprof.unrecorded_gc_samples++; rb_postponed_job_register_one(0, stackprof_job_record_gc, (void*)0); } else {