ext/stackprof.c in stackprof-0.2.3 vs ext/stackprof.c in stackprof-0.2.4
- old
+ new
@@ -24,16 +24,22 @@
st_table *lines;
} frame_data_t;
static struct {
int running;
+ int raw;
+ int aggregate;
+
VALUE mode;
VALUE interval;
- VALUE raw;
- size_t raw_sample_index;
VALUE out;
+ VALUE *raw_samples;
+ size_t raw_samples_len;
+ size_t raw_samples_capa;
+ size_t raw_sample_index;
+
size_t overall_signals;
size_t overall_samples;
size_t during_gc;
st_table *frames;
@@ -41,11 +47,11 @@
int lines_buffer[BUF_SIZE];
} _stackprof;
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_frames, sym_out;
+static VALUE sym_version, sym_mode, sym_interval, sym_raw, sym_frames, sym_out, sym_aggregate;
static VALUE sym_gc_samples, objtracer;
static VALUE gc_hook;
static VALUE rb_mStackProf;
static void stackprof_newobj_handler(VALUE, void*);
@@ -54,11 +60,12 @@
static VALUE
stackprof_start(int argc, VALUE *argv, VALUE self)
{
struct sigaction sa;
struct itimerval timer;
- VALUE opts = Qnil, mode = Qnil, interval = Qnil, raw = Qfalse, out = Qfalse;
+ VALUE opts = Qnil, mode = Qnil, interval = Qnil, out = Qfalse;
+ int raw = 0, aggregate = 1;
if (_stackprof.running)
return Qfalse;
rb_scan_args(argc, argv, "0:", &opts);
@@ -67,11 +74,13 @@
mode = rb_hash_aref(opts, sym_mode);
interval = rb_hash_aref(opts, sym_interval);
out = rb_hash_aref(opts, sym_out);
if (RTEST(rb_hash_aref(opts, sym_raw)))
- raw = rb_ary_new();
+ raw = 1;
+ if (rb_hash_lookup2(opts, sym_aggregate, Qundef) == Qfalse)
+ aggregate = 0;
}
if (!RTEST(mode)) mode = sym_wall;
if (!_stackprof.frames) {
_stackprof.frames = st_init_numtable();
@@ -104,10 +113,11 @@
rb_raise(rb_eArgError, "unknown profiler mode");
}
_stackprof.running = 1;
_stackprof.raw = raw;
+ _stackprof.aggregate = aggregate;
_stackprof.mode = mode;
_stackprof.interval = interval;
_stackprof.out = out;
return Qtrue;
@@ -232,13 +242,31 @@
st_foreach(_stackprof.frames, frame_i, (st_data_t)frames);
st_free_table(_stackprof.frames);
_stackprof.frames = NULL;
- if (RTEST(_stackprof.raw)) {
- rb_hash_aset(results, sym_raw, _stackprof.raw);
- _stackprof.raw = Qfalse;
+ if (_stackprof.raw && _stackprof.raw_samples_len) {
+ size_t len, n, o;
+ VALUE raw_samples = 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));
+
+ for (o = 0, n++; o < len; n++, o++)
+ rb_ary_push(raw_samples, rb_obj_id(_stackprof.raw_samples[n]));
+ rb_ary_push(raw_samples, SIZET2NUM((size_t)_stackprof.raw_samples[n]));
+ }
+
+ free(_stackprof.raw_samples);
+ _stackprof.raw_samples = NULL;
+ _stackprof.raw_samples_len = 0;
+ _stackprof.raw_samples_capa = 0;
+ _stackprof.raw_sample_index = 0;
+ _stackprof.raw = 0;
+
+ rb_hash_aset(results, sym_raw, raw_samples);
}
if (argc == 1)
_stackprof.out = argv[0];
@@ -313,41 +341,48 @@
void
stackprof_record_sample()
{
int num, i, n;
- int raw_mode = RTEST(_stackprof.raw);
VALUE prev_frame = Qnil;
- size_t raw_len;
_stackprof.overall_samples++;
num = rb_profile_frames(0, sizeof(_stackprof.frames_buffer), _stackprof.frames_buffer, _stackprof.lines_buffer);
- if (raw_mode) {
+ if (_stackprof.raw) {
int found = 0;
- raw_len = RARRAY_LEN(_stackprof.raw);
- if (RARRAY_LEN(_stackprof.raw) > 0 && RARRAY_AREF(_stackprof.raw, _stackprof.raw_sample_index) == INT2FIX(num)) {
+ if (!_stackprof.raw_samples) {
+ _stackprof.raw_samples_capa = num * 100;
+ _stackprof.raw_samples = malloc(sizeof(VALUE) * _stackprof.raw_samples_capa);
+ }
+
+ if (_stackprof.raw_samples_capa <= _stackprof.raw_samples_len + num) {
+ _stackprof.raw_samples_capa *= 2;
+ _stackprof.raw_samples = realloc(_stackprof.raw_samples, _stackprof.raw_samples_capa);
+ }
+
+ if (_stackprof.raw_samples_len > 0 && _stackprof.raw_samples[_stackprof.raw_sample_index] == (VALUE)num) {
for (i = num-1, n = 0; i >= 0; i--, n++) {
VALUE frame = _stackprof.frames_buffer[i];
- if (RARRAY_AREF(_stackprof.raw, _stackprof.raw_sample_index + 1 + n) != rb_obj_id(frame))
+ if (_stackprof.raw_samples[_stackprof.raw_sample_index + 1 + n] != frame)
break;
}
if (i == -1) {
- RARRAY_ASET(_stackprof.raw, raw_len-1, LONG2NUM(NUM2LONG(RARRAY_AREF(_stackprof.raw, raw_len-1))+1));
+ _stackprof.raw_samples[_stackprof.raw_samples_len-1] += 1;
found = 1;
}
}
if (!found) {
- _stackprof.raw_sample_index = raw_len;
- rb_ary_push(_stackprof.raw, INT2FIX(num));
+ _stackprof.raw_sample_index = _stackprof.raw_samples_len;
+ _stackprof.raw_samples[_stackprof.raw_samples_len++] = (VALUE)num;
for (i = num-1; i >= 0; i--) {
VALUE frame = _stackprof.frames_buffer[i];
- rb_ary_push(_stackprof.raw, rb_obj_id(frame));
+ _stackprof.raw_samples[_stackprof.raw_samples_len++] = frame;
}
- rb_ary_push(_stackprof.raw, INT2FIX(1));
+ _stackprof.raw_samples[_stackprof.raw_samples_len++] = (VALUE)1;
}
}
for (i = 0; i < num; i++) {
int line = _stackprof.lines_buffer[i];
@@ -356,17 +391,17 @@
frame_data->total_samples++;
if (i == 0) {
frame_data->caller_samples++;
- } else {
+ } else if (_stackprof.aggregate) {
if (!frame_data->edges)
frame_data->edges = st_init_numtable();
st_numtable_increment(frame_data->edges, (st_data_t)prev_frame, 1);
}
- if (line > 0) {
+ if (_stackprof.aggregate && line > 0) {
if (!frame_data->lines)
frame_data->lines = st_init_numtable();
size_t half = (size_t)1<<(8*SIZEOF_SIZE_T/2);
size_t increment = i == 0 ? half + 1 : half;
st_numtable_increment(frame_data->lines, (st_data_t)line, increment);
@@ -426,12 +461,10 @@
}
static void
stackprof_gc_mark(void *data)
{
- if (RTEST(_stackprof.raw))
- rb_gc_mark(_stackprof.raw);
if (RTEST(_stackprof.out))
rb_gc_mark(_stackprof.out);
if (_stackprof.frames)
st_foreach(_stackprof.frames, frame_mark_i, 0);
@@ -470,28 +503,31 @@
}
void
Init_stackprof(void)
{
- sym_object = ID2SYM(rb_intern("object"));
- sym_custom = ID2SYM(rb_intern("custom"));
- sym_wall = ID2SYM(rb_intern("wall"));
- sym_cpu = ID2SYM(rb_intern("cpu"));
- sym_name = ID2SYM(rb_intern("name"));
- sym_file = ID2SYM(rb_intern("file"));
- sym_line = ID2SYM(rb_intern("line"));
- sym_total_samples = ID2SYM(rb_intern("total_samples"));
- sym_gc_samples = ID2SYM(rb_intern("gc_samples"));
- sym_missed_samples = ID2SYM(rb_intern("missed_samples"));
- sym_samples = ID2SYM(rb_intern("samples"));
- sym_edges = ID2SYM(rb_intern("edges"));
- sym_lines = ID2SYM(rb_intern("lines"));
- sym_version = ID2SYM(rb_intern("version"));
- sym_mode = ID2SYM(rb_intern("mode"));
- sym_interval = ID2SYM(rb_intern("interval"));
- sym_raw = ID2SYM(rb_intern("raw"));
- sym_out = ID2SYM(rb_intern("out"));
- sym_frames = ID2SYM(rb_intern("frames"));
+#define S(name) sym_##name = ID2SYM(rb_intern(#name));
+ S(object);
+ S(custom);
+ S(wall);
+ S(cpu);
+ S(name);
+ S(file);
+ S(line);
+ S(total_samples);
+ S(gc_samples);
+ S(missed_samples);
+ S(samples);
+ S(edges);
+ S(lines);
+ S(version);
+ S(mode);
+ S(interval);
+ S(raw);
+ S(out);
+ S(frames);
+ S(aggregate);
+#undef S
gc_hook = Data_Wrap_Struct(rb_cObject, stackprof_gc_mark, NULL, NULL);
rb_global_variable(&gc_hook);
rb_mStackProf = rb_define_module("StackProf");