class RubyProf::Profile
Public Class Methods
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; }
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
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
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; }
# 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
# 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
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; }
Returns whether a profile is currently paused.
static VALUE prof_paused(VALUE self) { prof_profile_t* profile = prof_get_profile(self); return profile->paused; }
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); }
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; }
Returns whether a profile is currently running.
static VALUE prof_running(VALUE self) { prof_profile_t* profile = prof_get_profile(self); return profile->running; }
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; }
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; }
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; }