class RubyProf::Profile

Public Class Methods

RubyProf::Profile.new(mode, exclude_threads) → instance click to toggle source

Returns a new profiler.

Parameters

mode

Measure mode (optional). Specifies the profile measure mode. If not specified, defaults to RubyProf::WALL_TIME.

exclude_threads

Threads to exclude from the profiling results (optional).

static VALUE
prof_initialize(int argc,  VALUE *argv, VALUE self)
{
    prof_profile_t* profile = prof_get_profile(self);
    VALUE mode;
    prof_measure_mode_t measurer = MEASURE_WALL_TIME;
    VALUE exclude_threads;
    int i;
    
    switch (rb_scan_args(argc, argv, "02", &mode, &exclude_threads))
    {
      case 0:
      {
        measurer = MEASURE_WALL_TIME;
        exclude_threads = rb_ary_new();
        break;
      }
      case 1:
      {
        measurer = (prof_measure_mode_t)NUM2INT(mode);
        exclude_threads = rb_ary_new();
        break;
      }
      case 2:
      {
        Check_Type(exclude_threads, T_ARRAY);
        measurer = (prof_measure_mode_t)NUM2INT(mode);
        break;
      }
    }

    profile->measurer = prof_get_measurer(measurer);

    for (i = 0; i < RARRAY_LEN(exclude_threads); i++)
    {
        VALUE thread = rb_ary_entry(exclude_threads, i);
        VALUE thread_id = rb_obj_id(thread);
        st_insert(profile->exclude_threads_tbl, thread_id, Qtrue);
    }

    return self;
}
profile {block} → RubyProf::Result click to toggle source

Profiles the specified block and returns a RubyProf::Result object.

static VALUE
prof_profile(int argc,  VALUE *argv, VALUE klass)
{
    int result;
    VALUE profile = rb_class_new_instance(argc, argv, cProfile);

    if (!rb_block_given_p())
    {
        rb_raise(rb_eArgError, "A block must be provided to the profile method.");
    }

    prof_start(profile);
    rb_protect(rb_yield, profile, &result);
    return prof_stop(profile);
}

Public Instance Methods

detect_recursion(thread) click to toggle source

This method detect recursive calls in the call graph.

# File lib/ruby-prof/profile.rb, line 15
def detect_recursion(thread)
  visited_methods = Hash.new do |hash, key|
    hash[key] = 0
  end

  visitor = CallInfoVisitor.new(thread)
  visitor.visit do |call_info, event|
    case event
    when :enter
      visited_methods[call_info.target] += 1
      call_info.recursive = (visited_methods[call_info.target] > 1)
    when :exit
      visited_methods[call_info.target] -= 1
      if visited_methods[call_info.target] == 0
        visited_methods.delete(call_info.target)
      end
    end
  end
end
eliminate_methods!(matchers) click to toggle source

eliminate some calls from the graph by merging the information into callers. matchers can be a list of strings or regular expressions or the name of a file containing regexps.

# File lib/ruby-prof/profile.rb, line 37
def eliminate_methods!(matchers)
  matchers = read_regexps_from_file(matchers) if matchers.is_a?(String)
  eliminated = []
  threads.each do |thread|
    matchers.each{ |matcher| eliminated.concat(eliminate_methods(thread.methods, matcher)) }
  end
  eliminated
end
pause → RubyProf click to toggle source

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;
}
paused? → boolean click to toggle source

Returns whether a profile is currently paused.

static VALUE
prof_paused(VALUE self)
{
    prof_profile_t* profile = prof_get_profile(self);
    return profile->paused;
}
post_process() click to toggle source

This method gets called once profiling has been completed but before results are returned to the user. Thus it provides a hook to do any necessary post-processing on the call graph.

# File lib/ruby-prof/profile.rb, line 8
def post_process
  self.threads.each do |thread|
    detect_recursion(thread)
  end
end
resume {block} → RubyProf click to toggle source

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;
}
running? → boolean click to toggle source

Returns whether a profile is currently running.

static VALUE
prof_running(VALUE self)
{
    prof_profile_t* profile = prof_get_profile(self);
    return profile->running;
}
start → RubyProf click to toggle source

Starts recording profile data.

static VALUE
prof_start(VALUE self)
{
    char* trace_file_name;

    prof_profile_t* profile = prof_get_profile(self);
        
    if (profile->running == Qtrue)
    {
        rb_raise(rb_eRuntimeError, "RubyProf.start was already called");
    }

#ifndef RUBY_VM
        if (pCurrentProfile != NULL)
    {
        rb_raise(rb_eRuntimeError, "Only one profile can run at a time on Ruby 1.8.*");
    }
#endif

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


    /* open trace file if environment wants it */
    trace_file_name = getenv("RUBY_PROF_TRACE");
    if (trace_file_name != NULL) 
    {
      if (strcmp(trace_file_name, "stdout") == 0) 
      {
        trace_file = stdout;
      } 
      else if (strcmp(trace_file_name, "stderr") == 0)
      {
        trace_file = stderr;
      }
      else 
      {
        trace_file = fopen(trace_file_name, "w");
      }
    }

    prof_install_hook(self);
    return self;
}
stop → self click to toggle source

Stops collecting profile data.

static VALUE
prof_stop(VALUE self)
{
    prof_profile_t* profile = prof_get_profile(self);

    if (profile->running == Qfalse)
    {
        rb_raise(rb_eRuntimeError, "RubyProf.start was not yet called");
    }
  
    prof_remove_hook();

    /* close trace file if open */
    if (trace_file != NULL) 
    {
      if (trace_file !=stderr && trace_file != stdout)
      {
#ifdef _MSC_VER
          _fcloseall();
#else
        fclose(trace_file);
#endif
      }
      trace_file = NULL;
    }
    
    prof_pop_threads(profile);

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

    /* Post process result */
    rb_funcall(self, rb_intern("post_process") , 0);

    return self;
}
threads → Array of RubyProf::Thread click to toggle source

Returns an array of RubyProf::Thread instances that were executed while the the program was being run.

static VALUE
prof_threads(VALUE self)
{
        VALUE result = rb_ary_new();
    prof_profile_t* profile = prof_get_profile(self);
    st_foreach(profile->threads_tbl, collect_threads, result);
    return result;
}