Skip to content

Commit

Permalink
Revert "Remove pause/resume support."
Browse files Browse the repository at this point in the history
This reverts commit 69e3fe0.

Turns out Rails usings pause/resume.  Sigh.
  • Loading branch information
Charlie Savage committed Jan 7, 2013
1 parent 0048380 commit 2460523
Show file tree
Hide file tree
Showing 8 changed files with 306 additions and 2 deletions.
28 changes: 27 additions & 1 deletion ext/ruby_prof/rp_stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@

#define INITIAL_STACK_SIZE 8

void
prof_frame_pause(prof_frame_t *frame, double current_measurement)
{
if (frame && prof_frame_is_unpaused(frame))
frame->pause_time = current_measurement;
}

void
prof_frame_unpause(prof_frame_t *frame, double current_measurement)
{
if (frame && prof_frame_is_paused(frame)) {
frame->dead_time += (current_measurement - frame->pause_time);
frame->pause_time = -1;
}
}


/* Creates a stack of prof_frame_t to keep track
of timings for active methods. */
prof_stack_t *
Expand Down Expand Up @@ -47,6 +64,7 @@ prof_stack_push(prof_stack_t *stack, double measurement)
result->child_time = 0;
result->switch_time = 0;
result->wait_time = 0;
result->dead_time = 0;
result->depth = (int)(stack->ptr - stack->start); // shortening of 64 bit into 32
result->start_time = measurement;

Expand All @@ -66,6 +84,11 @@ prof_stack_pop(prof_stack_t *stack, double measurement)

double total_time;
double self_time;
#ifdef _MSC_VER
BOOL frame_paused;
#else
_Bool frame_paused;
#endif

/* Frame can be null. This can happen if RubProf.start is called from
a method that exits. And it can happen if an exception is raised
Expand All @@ -77,7 +100,8 @@ prof_stack_pop(prof_stack_t *stack, double measurement)
frame = --stack->ptr;

/* Calculate the total time this method took */
total_time = measurement - frame->start_time;
//prof_frame_unpause(frame, measurement);
total_time = measurement - frame->start_time - frame->dead_time;
self_time = total_time - frame->child_time - frame->wait_time;

/* Update information about the current method */
Expand All @@ -91,6 +115,8 @@ prof_stack_pop(prof_stack_t *stack, double measurement)
if (parent_frame)
{
parent_frame->child_time += total_time;
parent_frame->dead_time += frame->dead_time;

call_info->line = parent_frame->line;
}

Expand Down
8 changes: 8 additions & 0 deletions ext/ruby_prof/rp_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,18 @@ typedef struct
double switch_time; /* Time at switch to different thread */
double wait_time;
double child_time;
double pause_time; // Time pause() was initiated
double dead_time; // Time to ignore (i.e. total amount of time between pause/resume blocks)
int depth;
unsigned int line;
} prof_frame_t;

#define prof_frame_is_paused(f) (f->pause_time >= 0)
#define prof_frame_is_unpaused(f) (f->pause_time < 0)
void prof_frame_pause(prof_frame_t*, double current_measurement);
void prof_frame_unpause(prof_frame_t*, double current_measurement);


/* Current stack of active methods.*/
typedef struct
{
Expand Down
23 changes: 23 additions & 0 deletions ext/ruby_prof/rp_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,29 @@ switch_thread(void* prof, VALUE thread_id)
return thread_data;
}


int pause_thread(st_data_t key, st_data_t value, st_data_t data)
{
thread_data_t* thread_data = (thread_data_t *) value;
double measurement = (double) data;

prof_frame_t* frame = prof_stack_peek(thread_data->stack);
prof_frame_pause(frame, measurement);

return ST_CONTINUE;
}

int unpause_thread(st_data_t key, st_data_t value, st_data_t data)
{
thread_data_t* thread_data = (thread_data_t *) value;
double measurement = (double) data;

prof_frame_t* frame = prof_stack_peek(thread_data->stack);
prof_frame_unpause(frame, measurement);

return ST_CONTINUE;
}

static int
collect_methods(st_data_t key, st_data_t value, st_data_t result)
{
Expand Down
2 changes: 2 additions & 0 deletions ext/ruby_prof/rp_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ thread_data_t* switch_thread(void* prof, VALUE thread_id);
void threads_table_free(st_table *table);
VALUE prof_thread_wrap(thread_data_t *thread);
void prof_thread_mark(thread_data_t *thread);
int pause_thread(st_data_t key, st_data_t value, st_data_t data);
int unpause_thread(st_data_t key, st_data_t value, st_data_t data);

#endif //__RP_THREAD__
71 changes: 70 additions & 1 deletion ext/ruby_prof/ruby_prof.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,18 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
call_info_table_insert(frame->call_info->call_infos, method->key, call_info);
prof_add_call_info(method->call_infos, call_info);
}

// Unpause the parent frame. If currently paused then:
// 1) The child frame will begin paused.
// 2) The parent will inherit the child's dead time.
prof_frame_unpause(frame, measurement);
}

/* Push a new frame onto the stack for a new c-call or ruby call (into a method) */
frame = prof_stack_push(thread_data->stack, measurement);
frame->call_info = call_info;
frame->call_info->depth = frame->depth;
frame->pause_time = profile->paused == Qtrue ? measurement : -1;
frame->line = rb_sourceline();
break;
}
Expand Down Expand Up @@ -454,6 +460,17 @@ prof_initialize(int argc, VALUE *argv, VALUE self)
return self;
}

/* call-seq:
paused? -> boolean
Returns whether a profile is currently paused.*/
static VALUE
prof_paused(VALUE self)
{
prof_profile_t* profile = prof_get_profile(self);
return profile->paused;
}

/* call-seq:
running? -> boolean
Expand Down Expand Up @@ -489,9 +506,11 @@ prof_start(VALUE self)
#endif

profile->running = Qtrue;
profile->paused = Qfalse;
profile->last_thread_data = NULL;

/* open trace file if environment wants it */

/* open trace file if environment wants it */
trace_file_name = getenv("RUBY_PROF_TRACE");
if (trace_file_name != NULL)
{
Expand All @@ -513,6 +532,52 @@ prof_start(VALUE self)
return self;
}

/* call-seq:
pause -> RubyProf
Pauses collecting profile data. */
static VALUE
prof_pause(VALUE self)
{
prof_profile_t* profile = prof_get_profile(self);
if (profile->running == Qfalse)
{
rb_raise(rb_eRuntimeError, "RubyProf is not running.");
}

if (profile->paused == Qfalse)
{
profile->paused = Qtrue;
profile->measurement_at_pause_resume = profile->measurer->measure();
st_foreach(profile->threads_tbl, pause_thread, (st_data_t) profile);
}

return self;
}

/* call-seq:
resume {block} -> RubyProf
Resumes recording profile data.*/
static VALUE
prof_resume(VALUE self)
{
prof_profile_t* profile = prof_get_profile(self);
if (profile->running == Qfalse)
{
rb_raise(rb_eRuntimeError, "RubyProf is not running.");
}

if (profile->paused == Qtrue)
{
profile->paused = Qfalse;
profile->measurement_at_pause_resume = profile->measurer->measure();
st_foreach(profile->threads_tbl, unpause_thread, (st_data_t) profile);
}

return rb_block_given_p() ? rb_ensure(rb_yield, self, prof_pause, self) : self;
}

/* call-seq:
stop -> self
Expand Down Expand Up @@ -547,6 +612,7 @@ prof_stop(VALUE self)

/* Unset the last_thread_data (very important!)
and the threads table */
profile->running = profile->paused = Qfalse;
profile->last_thread_data = NULL;

/* Post process result */
Expand Down Expand Up @@ -605,6 +671,9 @@ void Init_ruby_prof()
rb_define_method(cProfile, "initialize", prof_initialize, -1);
rb_define_method(cProfile, "start", prof_start, 0);
rb_define_method(cProfile, "stop", prof_stop, 0);
rb_define_method(cProfile, "resume", prof_resume, 0);
rb_define_method(cProfile, "pause", prof_pause, 0);
rb_define_method(cProfile, "running?", prof_running, 0);
rb_define_method(cProfile, "paused?", prof_paused, 0);
rb_define_method(cProfile, "threads", prof_threads, 0);
}
2 changes: 2 additions & 0 deletions ext/ruby_prof/ruby_prof.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ void method_key(prof_method_key_t* key, VALUE klass, ID mid);
typedef struct
{
VALUE running;
VALUE paused;
prof_measurer_t* measurer;
VALUE threads;
st_table* threads_tbl;
st_table* exclude_threads_tbl;
thread_data_t* last_thread_data;
double measurement_at_pause_resume;
} prof_profile_t;


Expand Down
12 changes: 12 additions & 0 deletions lib/ruby-prof/compatibility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ def self.start
@profile.start
end

def self.pause
ensure_running!
disable_gc_stats_if_needed
@profile.pause
end

def self.running?
if defined?(@profile) and @profile
@profile.running?
Expand All @@ -111,6 +117,12 @@ def self.running?
end
end

def self.resume
ensure_running!
enable_gc_stats_if_needed
@profile.resume
end

def self.stop
ensure_running!
result = @profile.stop
Expand Down
Loading

0 comments on commit 2460523

Please sign in to comment.