class RubyProf::Profile - ruby-prof

# class RubyProf::Profile

### Public Class Methods

new() click to toggle source
new(options)

Returns a new profiler. Possible options for the options hash are:

measure_mode

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

exclude_threads

  Threads to exclude from the profiling results.

include_threads

  Focus profiling on only the given threads. This will ignore all other threads.

merge_fibers

  Whether to merge all fibers under a given thread. This should be used when profiling for a callgrind printer.

    static VALUE
    prof_initialize(int argc,  VALUE *argv, VALUE self)
    {
        prof_profile_t* profile = prof_get_profile(self);
        VALUE mode_or_options;
        VALUE mode = Qnil;
        VALUE exclude_threads = Qnil;
        VALUE include_threads = Qnil;
        VALUE merge_fibers = Qnil;
        VALUE exclude_common = Qnil;
        int i;

        switch (rb_scan_args(argc, argv, "02", &mode_or_options, &exclude_threads)) {
        case 0:
            break;
        case 1:
            if (FIXNUM_P(mode_or_options)) {
                mode = mode_or_options;
            }
            else {
                Check_Type(mode_or_options, T_HASH);
                mode = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("measure_mode")));
                merge_fibers = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("merge_fibers")));
                exclude_common = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("exclude_common")));
                exclude_threads = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("exclude_threads")));
                include_threads = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("include_threads")));
            }
            break;
        case 2:
            Check_Type(exclude_threads, T_ARRAY);
            break;
        }

        if (mode == Qnil) {
            mode = INT2NUM(MEASURE_WALL_TIME);
        } else {
            Check_Type(mode, T_FIXNUM);
        }
        profile->measurer = prof_get_measurer(NUM2INT(mode));
        profile->merge_fibers = merge_fibers != Qnil && merge_fibers != Qfalse;

        if (exclude_threads != Qnil) {
            Check_Type(exclude_threads, T_ARRAY);
            assert(profile->exclude_threads_tbl == NULL);
            profile->exclude_threads_tbl = threads_table_create();
            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);
            }
        }

        if (include_threads != Qnil) {
            Check_Type(include_threads, T_ARRAY);
            assert(profile->include_threads_tbl == NULL);
            profile->include_threads_tbl = threads_table_create();
            for (i = 0; i < RARRAY_LEN(include_threads); i++) {
                VALUE thread = rb_ary_entry(include_threads, i);
                VALUE thread_id = rb_obj_id(thread);
                st_insert(profile->include_threads_tbl, thread_id, Qtrue);
            }
        }

        if (RTEST(exclude_common)) {
            prof_exclude_common_methods(self);
        }

        return self;
    }

profile(&block) → self click to toggle source
profile(options, &block) → self

Profiles the specified block and returns a RubyProf::Profile object. Arguments are passed to Profile initialize method.

    static VALUE
    prof_profile_class(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

exclude_common_methods!() click to toggle source

Hides methods that, when represented as a call graph, have extremely large in and out degrees and make navigation impossible.

    # File lib/ruby-prof/profile.rb, line 11
    def exclude_common_methods!
      ExcludeCommonMethods.apply!(self)
    end

exclude_method!(p1, p2) click to toggle source

    static VALUE
    prof_exclude_method(VALUE self, VALUE klass, VALUE sym)
    {
        prof_profile_t* profile = prof_get_profile(self);
        ID mid = SYM2ID(sym);

        prof_method_key_t key;
        prof_method_t *method;

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

        method_key(&key, klass, mid);
        method = method_table_lookup(profile->exclude_methods_tbl, &key);

        if (!method) {
          method = prof_method_create_excluded(klass, mid);
          method_table_insert(profile->exclude_methods_tbl, method->key, method);
        }

        return self;
    }

exclude_methods!(mod, *method_or_methods) click to toggle source

    # File lib/ruby-prof/profile.rb, line 15
    def exclude_methods!(mod, *method_or_methods)
      [method_or_methods].flatten.each do |name|
        exclude_method!(mod, name)
      end
    end

exclude_singleton_methods!(mod, *method_or_methods) click to toggle source

    # File lib/ruby-prof/profile.rb, line 21
    def exclude_singleton_methods!(mod, *method_or_methods)
      exclude_methods!(mod.singleton_class, *method_or_methods)
    end

pause → self 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;
    }

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

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

    static VALUE
    prof_profile_object(VALUE self)
    {
        int result;
        if (!rb_block_given_p())
        {
            rb_raise(rb_eArgError, "A block must be provided to the profile method.");
        }

        prof_start(self);
        rb_protect(rb_yield, self, &result);
        return prof_stop(self);

    }

resume → self click to toggle source
resume(&block) → self

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 → self 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");
        }

        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(self);

        /* 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;

        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;
    }