Skip to content

Commit

Permalink
Merge pull request #213 from tmm1/raw-line-numbers
Browse files Browse the repository at this point in the history
Add raw line numbers for raw mode
  • Loading branch information
tenderlove authored Jul 9, 2023
2 parents ef8b134 + 03369b9 commit 51b71bf
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
33 changes: 27 additions & 6 deletions ext/stackprof/stackprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ static struct {
VALUE metadata;
int ignore_gc;

VALUE *raw_samples;
uint64_t *raw_samples;
size_t raw_samples_len;
size_t raw_samples_capa;
size_t raw_sample_index;
Expand Down Expand Up @@ -133,7 +133,7 @@ static struct {

static VALUE sym_object, sym_wall, sym_cpu, sym_custom, sym_name, sym_file, sym_line;
static VALUE sym_samples, sym_total_samples, sym_missed_samples, sym_edges, sym_lines;
static VALUE sym_version, sym_mode, sym_interval, sym_raw, sym_metadata, sym_frames, sym_ignore_gc, sym_out;
static VALUE sym_version, sym_mode, sym_interval, sym_raw, sym_raw_lines, sym_metadata, sym_frames, sym_ignore_gc, sym_out;
static VALUE sym_aggregate, sym_raw_sample_timestamps, sym_raw_timestamp_deltas, sym_state, sym_marking, sym_sweeping;
static VALUE sym_gc_samples, objtracer;
static VALUE gc_hook;
Expand Down Expand Up @@ -374,14 +374,23 @@ stackprof_results(int argc, VALUE *argv, VALUE self)
size_t len, n, o;
VALUE raw_sample_timestamps, raw_timestamp_deltas;
VALUE raw_samples = rb_ary_new_capa(_stackprof.raw_samples_len);
VALUE raw_lines = rb_ary_new_capa(_stackprof.raw_samples_len);

for (n = 0; n < _stackprof.raw_samples_len; n++) {
len = (size_t)_stackprof.raw_samples[n];
rb_ary_push(raw_samples, SIZET2NUM(len));
rb_ary_push(raw_lines, SIZET2NUM(len));

for (o = 0, n++; o < len; n++, o++) {
// Line is in the upper 16 bits
rb_ary_push(raw_lines, INT2NUM(_stackprof.raw_samples[n] >> 48));

VALUE frame = _stackprof.raw_samples[n] & ~((uint64_t)0xFFFF << 48);
rb_ary_push(raw_samples, PTR2NUM(frame));
}

for (o = 0, n++; o < len; n++, o++)
rb_ary_push(raw_samples, PTR2NUM(_stackprof.raw_samples[n]));
rb_ary_push(raw_samples, SIZET2NUM((size_t)_stackprof.raw_samples[n]));
rb_ary_push(raw_lines, SIZET2NUM((size_t)_stackprof.raw_samples[n]));
}

free(_stackprof.raw_samples);
Expand All @@ -391,6 +400,7 @@ stackprof_results(int argc, VALUE *argv, VALUE self)
_stackprof.raw_sample_index = 0;

rb_hash_aset(results, sym_raw, raw_samples);
rb_hash_aset(results, sym_raw_lines, raw_lines);

raw_sample_timestamps = rb_ary_new_capa(_stackprof.raw_sample_times_len);
raw_timestamp_deltas = rb_ary_new_capa(_stackprof.raw_sample_times_len);
Expand Down Expand Up @@ -520,7 +530,12 @@ stackprof_record_sample_for_stack(int num, uint64_t sample_timestamp, int64_t ti
* in the frames buffer that came from Ruby. */
for (i = num-1, n = 0; i >= 0; i--, n++) {
VALUE frame = _stackprof.frames_buffer[i];
if (_stackprof.raw_samples[_stackprof.raw_sample_index + 1 + n] != frame)
int line = _stackprof.lines_buffer[i];

// Encode the line in to the upper 16 bits.
uint64_t key = ((uint64_t)line << 48) | (uint64_t)frame;

if (_stackprof.raw_samples[_stackprof.raw_sample_index + 1 + n] != key)
break;
}
if (i == -1) {
Expand All @@ -538,7 +553,12 @@ stackprof_record_sample_for_stack(int num, uint64_t sample_timestamp, int64_t ti
_stackprof.raw_samples[_stackprof.raw_samples_len++] = (VALUE)num;
for (i = num-1; i >= 0; i--) {
VALUE frame = _stackprof.frames_buffer[i];
_stackprof.raw_samples[_stackprof.raw_samples_len++] = frame;
int line = _stackprof.lines_buffer[i];

// Encode the line in to the upper 16 bits.
uint64_t key = ((uint64_t)line << 48) | (uint64_t)frame;

_stackprof.raw_samples[_stackprof.raw_samples_len++] = key;
}
_stackprof.raw_samples[_stackprof.raw_samples_len++] = (VALUE)1;
}
Expand Down Expand Up @@ -894,6 +914,7 @@ Init_stackprof(void)
S(mode);
S(interval);
S(raw);
S(raw_lines);
S(raw_sample_timestamps);
S(raw_timestamp_deltas);
S(out);
Expand Down
3 changes: 3 additions & 0 deletions test/test_stackprof.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,13 @@ def test_raw
after_monotonic = Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)

raw = profile[:raw]
raw_lines = profile[:raw_lines]
assert_equal 10, raw[-1]
assert_equal raw[0] + 2, raw.size
assert_equal 10, raw_lines[-1] # seen 10 times

offset = RUBY_VERSION >= '3' ? -3 : -2
assert_equal 140, raw_lines[offset] # sample caller is on 140
assert_includes profile[:frames][raw[offset]][:name], 'StackProfTest#test_raw'

assert_equal 10, profile[:raw_sample_timestamps].size
Expand Down

0 comments on commit 51b71bf

Please sign in to comment.