Skip to content

Commit

Permalink
better accuracy
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm1 committed Sep 21, 2012
1 parent 6f2b3ce commit 6ce45b8
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 31 deletions.
82 changes: 54 additions & 28 deletions ext/rblineprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ typedef struct {

static struct {
bool enabled;
char *last_file;
long last_line;

// single file mode, store filename and line data directly
char *source_filename;
Expand All @@ -30,14 +32,16 @@ static struct {
// regex mode, store file data in hash table
VALUE source_regex;
st_table *files;
sourcefile_t *last_file;
sourcefile_t *last_sourcefile;
}
rblineprof = {
.enabled = false,
.last_file = NULL,
.last_line = 0,
.source_filename = NULL,
.source_regex = Qfalse,
.files = NULL,
.last_file = NULL
.last_sourcefile = NULL
};

static uint64_t
Expand All @@ -49,6 +53,32 @@ timeofday_usec()
(uint64_t)tv.tv_usec;
}

static inline void
sourcefile_record(sourcefile_t *sourcefile, uint64_t now)
{
if (sourcefile->last_time && sourcefile->last_line) {
/* allocate space for per-line data the first time */
if (sourcefile->lines == NULL) {
sourcefile->nlines = sourcefile->last_line + 100;
sourcefile->lines = ALLOC_N(uint64_t, sourcefile->nlines);
MEMZERO(sourcefile->lines, uint64_t, sourcefile->nlines);
}

/* grow the per-line array if necessary */
if (sourcefile->last_line >= sourcefile->nlines) {
long prev_nlines = sourcefile->nlines;
sourcefile->nlines = sourcefile->last_line + 100;

REALLOC_N(sourcefile->lines, uint64_t, sourcefile->nlines);
MEMZERO(sourcefile->lines + prev_nlines, uint64_t, sourcefile->nlines - prev_nlines);
}

/* record the sample */
sourcefile->lines[sourcefile->last_line] += (now - sourcefile->last_time);
sourcefile->last_time = now;
}
}

static void
profiler_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
{
Expand All @@ -60,6 +90,12 @@ profiler_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
if (!file) return;
if (line <= 0) return;

// skip duplicate events fast
if (file == rblineprof.last_file && line == rblineprof.last_line)
return;
rblineprof.last_file = file;
rblineprof.last_line = line;

if (rblineprof.source_filename) { // single file mode
if (rblineprof.source_filename == file) {
sourcefile = &rblineprof.file;
Expand Down Expand Up @@ -90,34 +126,22 @@ profiler_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
if (sourcefile) {
uint64_t now = timeofday_usec();

if (sourcefile->last_time) {
/* allocate space for per-line data the first time */
if (sourcefile->lines == NULL) {
sourcefile->nlines = sourcefile->last_line + 100;
sourcefile->lines = ALLOC_N(uint64_t, sourcefile->nlines);
MEMZERO(sourcefile->lines, uint64_t, sourcefile->nlines);
}

/* grow the per-line array if necessary */
if (sourcefile->last_line >= sourcefile->nlines) {
long prev_nlines = sourcefile->nlines;
sourcefile->nlines = sourcefile->last_line + 100;

REALLOC_N(sourcefile->lines, uint64_t, sourcefile->nlines);
MEMZERO(sourcefile->lines + prev_nlines, uint64_t, sourcefile->nlines - prev_nlines);
}

/* record the sample */
sourcefile->lines[sourcefile->last_line] += (now - sourcefile->last_time);
/* increment if the line in the current file changed */
if (sourcefile->last_line != line) {
sourcefile_record(sourcefile, now);
}

sourcefile->last_time = now;
sourcefile->last_line = line;

if (rblineprof.last_file && rblineprof.last_file != sourcefile)
rblineprof.last_file->last_time = 0;
if (!sourcefile->last_time)
sourcefile->last_time = now;

/* if we came from another file, increment there and reset */
if (rblineprof.last_sourcefile && rblineprof.last_sourcefile != sourcefile) {
sourcefile_record(rblineprof.last_sourcefile, now);
rblineprof.last_sourcefile->last_line = 0;
}

rblineprof.last_file = sourcefile;
rblineprof.last_sourcefile = sourcefile;
}
}

Expand Down Expand Up @@ -181,8 +205,10 @@ lineprof(VALUE self, VALUE filename)
rb_raise(rb_eArgError, "argument must be String or Regexp");
}

// cleanup
// reset state
rblineprof.last_file = NULL;
rblineprof.last_line = 0;
rblineprof.last_sourcefile = NULL;
st_foreach(rblineprof.files, cleanup_files, 0);
if (rblineprof.file.lines) {
xfree(rblineprof.file.lines);
Expand All @@ -191,7 +217,7 @@ lineprof(VALUE self, VALUE filename)
}

rblineprof.enabled = true;
rb_add_event_hook(profiler_hook, RUBY_EVENT_LINE);
rb_add_event_hook(profiler_hook, RUBY_EVENT_ALL);
rb_ensure(rb_yield, Qnil, lineprof_ensure, self);

VALUE ret = rb_hash_new();
Expand Down
11 changes: 8 additions & 3 deletions test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
require 'rblineprof'

profile = lineprof(/./) do
1000.times do
sleep 0.001

100.times do

sleep 0.001
1*2*3
4*5*6
7*8*9*10*11*12*13*14*15
Expand All @@ -15,8 +18,10 @@

File.readlines(__FILE__).each_with_index do |line, num|
if (sample = profile[__FILE__][num+1]) > 0
printf "% 6d | %s", sample, line
# printf "% 7d | %s", sample, line
printf "% 8.1fms | %s", sample/1000.0, line
else
printf " | %s", line
# printf " | %s", line
printf " | %s", line
end
end

0 comments on commit 6ce45b8

Please sign in to comment.