diff --git a/README.md b/README.md index 698f0a0..740444c 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,8 @@ Rbkit.start_profiling( enable_cpu_profiling: true, clock_type: :wall, cpu_profiling_mode: :sampling, - cpu_sampling_interval_usec: 1000 + cpu_sampling_interval_usec: 1000, + cpu_sampling_depth: 10 ) ``` @@ -122,6 +123,7 @@ Arguments: |clock_type | :wall/:cpu | :wall | Specifies clock type to use in CPU profiling | |cpu_profiling_mode | :sampling | :sampling | CPU profiling mode - currently only sampling | |cpu_sampling_interval_usec | Fixnums | 1000 | CPU Sampling interval un usec, if sampling mode | +|cpu_sampling_depth | Fixnums | 10 | Depth of stack frame collected by CPU sampler | ## Development diff --git a/ext/rbkit_sampling_profiler.c b/ext/rbkit_sampling_profiler.c index 06f94fb..33a1fe6 100644 --- a/ext/rbkit_sampling_profiler.c +++ b/ext/rbkit_sampling_profiler.c @@ -9,8 +9,11 @@ #define BUF_SIZE 2048 -static int signal_type; -static int clock_type; +static struct cpu_sampling_args { + int signal_type; + int clock_type; + int sampling_depth; +} args; queue_sample_func_ptr queue_cpu_sample_for_sending; #ifdef RBKIT_DEV @@ -30,7 +33,9 @@ static void sampling_job_handler(void *data_unused) { rbkit_cpu_sample *sample = malloc(sizeof(rbkit_cpu_sample)); - int collected_size = rb_profile_frames(start, sizeof(buff) / sizeof(VALUE), buff, lines); + int max_depth = sizeof(buff) / sizeof(VALUE); + int depth = (args.sampling_depth > max_depth) ? max_depth : args.sampling_depth; + int collected_size = rb_profile_frames(start, depth, buff, lines); rbkit_frame_data *frame_data = malloc(sizeof(rbkit_frame_data) * collected_size); sample->frames = frame_data; sample->frame_count = collected_size; @@ -89,7 +94,7 @@ static void install_signal_handler() { sa.sa_sigaction = signal_handler; sa.sa_flags = SA_RESTART | SA_SIGINFO; sigemptyset(&sa.sa_mask); - sigaction(signal_type, &sa, NULL); + sigaction(args.signal_type, &sa, NULL); } static void uninstall_signal_handler() { @@ -97,7 +102,7 @@ static void uninstall_signal_handler() { sa.sa_handler = SIG_IGN; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); - sigaction(signal_type, &sa, NULL); + sigaction(args.signal_type, &sa, NULL); #ifdef RBKIT_DEV fprintf(stderr, "Time spent in CPU sampling in usecs = %f(wall) %f(cpu)\n", total_wall_time_spent_in_sampling, total_cpu_time_spent_in_sampling); #endif @@ -109,23 +114,24 @@ static void start_sigprof_timer(int interval) { timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = interval; timer.it_value = timer.it_interval; - setitimer(clock_type, &timer, 0); + setitimer(args.clock_type, &timer, 0); } static void stop_sigprof_timer() { struct itimerval timer; memset(&timer, 0, sizeof(timer)); - setitimer(clock_type, &timer, 0); + setitimer(args.clock_type, &timer, 0); } -void rbkit_install_sampling_profiler(int wall_time, int interval, queue_sample_func_ptr func) { +void rbkit_install_sampling_profiler(int wall_time, int interval, int depth, queue_sample_func_ptr func) { queue_cpu_sample_for_sending = func; + args.sampling_depth = depth; if(wall_time) { - signal_type = SIGALRM; - clock_type = ITIMER_REAL; + args.signal_type = SIGALRM; + args.clock_type = ITIMER_REAL; } else { - signal_type = SIGPROF; - clock_type = ITIMER_PROF; + args.signal_type = SIGPROF; + args.clock_type = ITIMER_PROF; } install_signal_handler(); start_sigprof_timer(interval); diff --git a/ext/rbkit_sampling_profiler.h b/ext/rbkit_sampling_profiler.h index 5ce0535..a4d1901 100644 --- a/ext/rbkit_sampling_profiler.h +++ b/ext/rbkit_sampling_profiler.h @@ -19,6 +19,6 @@ typedef struct _rbkit_cpu_sample { typedef void (*queue_sample_func_ptr) (rbkit_cpu_sample *); -void rbkit_install_sampling_profiler(int wall_time, int interval, queue_sample_func_ptr func); +void rbkit_install_sampling_profiler(int wall_time, int interval, int depth, queue_sample_func_ptr func); void rbkit_uninstall_sampling_profiler(); #endif diff --git a/ext/rbkit_server.c b/ext/rbkit_server.c index 883d608..0b625c1 100644 --- a/ext/rbkit_server.c +++ b/ext/rbkit_server.c @@ -331,12 +331,12 @@ static void queue_cpu_sample_for_sending(rbkit_cpu_sample *sample) { msgpack_packer_free(packer); } -static VALUE start_sampling_profiler(VALUE self, VALUE clock_type, VALUE interval) { +static VALUE start_sampling_profiler(VALUE self, VALUE clock_type, VALUE interval, VALUE depth) { if (logger->sampling_profiler_enabled == Qtrue) return Qnil; if(!SYMBOL_P(clock_type)) rb_raise(rb_eArgError, "clock_type should be a symbol, either :wall or :cpu"); - rbkit_install_sampling_profiler(clock_type == ID2SYM(rb_intern("wall")), FIX2INT(interval), queue_cpu_sample_for_sending); + rbkit_install_sampling_profiler(clock_type == ID2SYM(rb_intern("wall")), FIX2INT(interval), FIX2INT(depth), queue_cpu_sample_for_sending); logger->sampling_profiler_enabled = Qtrue; return Qnil; } @@ -466,7 +466,7 @@ void Init_rbkit_server(void) { rb_define_method(rbkit_server, "stop_stat_server", stop_stat_server, 0); rb_define_method(rbkit_server, "start_stat_tracing", start_stat_tracing, 0); rb_define_method(rbkit_server, "stop_stat_tracing", stop_stat_tracing, 0); - rb_define_method(rbkit_server, "start_sampling_profiler", start_sampling_profiler, 2); + rb_define_method(rbkit_server, "start_sampling_profiler", start_sampling_profiler, 3); rb_define_method(rbkit_server, "stop_sampling_profiler", stop_sampling_profiler, 0); rb_define_method(rbkit_server, "poll_for_request", poll_for_request, 0); rb_define_method(rbkit_server, "send_objectspace_dump", send_objectspace_dump, 0); diff --git a/lib/rbkit.rb b/lib/rbkit.rb index 51dd701..2fc6e69 100644 --- a/lib/rbkit.rb +++ b/lib/rbkit.rb @@ -32,13 +32,13 @@ def self.start_server(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT def self.start_profiling(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT, enable_object_trace: true, enable_gc_stats: true, enable_cpu_profiling: true, clock_type: :wall, - cpu_profiling_mode: :sampling, cpu_sampling_interval_usec: 1000) + cpu_profiling_mode: :sampling, cpu_sampling_interval_usec: 1000, cpu_sampling_depth: 10) @server ||= Rbkit::Server.new(pub_port, request_port) @server.start(enable_object_trace: enable_object_trace, enable_gc_stats: enable_gc_stats, enable_cpu_profiling: enable_cpu_profiling, clock_type: clock_type, - cpu_sampling_interval_usec: cpu_sampling_interval_usec) + cpu_sampling_interval_usec: cpu_sampling_interval_usec, cpu_sampling_depth: cpu_sampling_depth) end # Stops profiling and brings down the rbkit server if it's running diff --git a/lib/rbkit/server.rb b/lib/rbkit/server.rb index 10a0361..0fb993d 100644 --- a/lib/rbkit/server.rb +++ b/lib/rbkit/server.rb @@ -11,6 +11,7 @@ def initialize(pub_port, request_port) @clock_type = :cpu @cpu_profiling_mode = :sampling @cpu_sampling_interval_usec = 1000 + @cpu_sampling_depth = 10 @respond_callback = nil @publish_callback = nil @gc_stats_timer = Rbkit::Timer.new(5) do @@ -23,7 +24,7 @@ def initialize(pub_port, request_port) end def start(enable_object_trace: false, enable_gc_stats: false, - enable_cpu_profiling: false, clock_type: nil, cpu_profiling_mode: nil, cpu_sampling_interval_usec: nil) + enable_cpu_profiling: false, clock_type: nil, cpu_profiling_mode: nil, cpu_sampling_interval_usec: nil, cpu_sampling_depth: nil) if @server_running || !start_stat_server(pub_port, request_port) $stderr.puts "Rbkit server couldn't bind to socket, check if it is already" \ " running. Profiling data will not be available." @@ -33,7 +34,8 @@ def start(enable_object_trace: false, enable_gc_stats: false, @cpu_profiling_mode = cpu_profiling_mode if cpu_profiling_mode @clock_type = clock_type if clock_type @cpu_sampling_interval_usec = cpu_sampling_interval_usec if cpu_sampling_interval_usec - start_cpu_profiling(clock_type: @clock_type, sampling_interval_usec: @cpu_sampling_interval_usec) if enable_cpu_profiling + @cpu_sampling_depth = cpu_sampling_depth if cpu_sampling_depth + start_cpu_profiling(clock_type: @clock_type, sampling_interval_usec: @cpu_sampling_interval_usec, sampling_depth: @cpu_sampling_depth) if enable_cpu_profiling @enable_gc_stats = enable_gc_stats @server_running = true @@ -77,7 +79,7 @@ def process_incoming_request(incoming_request) when "use_wall_time" @clock_type = :wall when "start_cpu_profiling" - start_cpu_profiling(clock_type: @clock_type, sampling_interval_usec: @cpu_sampling_interval_usec) + start_cpu_profiling(clock_type: @clock_type, sampling_interval_usec: @cpu_sampling_interval_usec, sampling_depth: @cpu_sampling_depth) when "stop_cpu_profiling" stop_cpu_profiling end @@ -93,10 +95,10 @@ def stop true end - def start_cpu_profiling(mode: :sampling, clock_type: :wall, sampling_interval_usec: 1000) + def start_cpu_profiling(mode: :sampling, clock_type: :wall, sampling_interval_usec: 1000, sampling_depth: 10) @cpu_profiling_mode = mode if mode == :sampling - start_sampling_profiler(clock_type, sampling_interval_usec) + start_sampling_profiler(clock_type, sampling_interval_usec, sampling_depth) else # TODO end diff --git a/spec/cpu_sampling_spec.rb b/spec/cpu_sampling_spec.rb index 64580f9..e54844d 100644 --- a/spec/cpu_sampling_spec.rb +++ b/spec/cpu_sampling_spec.rb @@ -1,43 +1,14 @@ require 'spec_helper' +require 'support/cpu_profiling_example' require 'support/cpu_sample_helpers' include CpuSampleHelpers describe 'CPU Sampling' do - let(:sampling_interval_in_usec) { 1000 } - - def io_intensive_operation - r, w = IO.pipe - IO.select([r], nil, nil, 1) - ensure - r.close - w.close - end - - def cpu_intensive_operation - 100000.times{|x| Math.sqrt(x)} - end - - class SampleClassForTest - class Sample2 - def baz(block) - instance_eval 'def zab(block) block.call end' - [self, zab(block)] - end - end - - def self.bar(block) - Sample2.new.baz(block) - end - - def foo(block) - self.class.bar(block) - end - end - before do server = Rbkit.start_profiling(enable_gc_stats: false, enable_object_trace: false, enable_cpu_profiling: true, clock_type: clock_type, - cpu_profiling_mode: :sampling, cpu_sampling_interval_usec: sampling_interval_in_usec) + cpu_profiling_mode: :sampling, cpu_sampling_interval_usec: sampling_interval_in_usec, + cpu_sampling_depth: stack_depth) Fiber.new { Fiber.yield SampleClassForTest.new.foo(operation) }.resume @@ -45,6 +16,10 @@ def foo(block) server.stop end + let(:sampling_interval_in_usec) { 1000 } + let(:stack_depth) { 10 } + let(:file) { File.absolute_path(File.join(__FILE__, '../support/cpu_profiling_example.rb')) } + context 'when using wall time' do let(:clock_type) { :wall } let(:operation) { lambda{ io_intensive_operation; cpu_intensive_operation; } } @@ -52,7 +27,7 @@ def foo(block) it 'should record the correct stack frames for io intensive operation' do # Make sure sampling can detect most expensive method expect(@messages).to have_message(Rbkit::EVENT_TYPES[:cpu_sample]) - expect(@messages).to have_most_cpu_samples_for("#{__FILE__}:8") + expect(@messages).to have_most_cpu_samples_for("#{file}:1") # Make sure stack trace is correct frames = most_frequent_sample(@messages) @@ -60,9 +35,9 @@ def foo(block) frame = frames[0] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'io_intensive_operation' - expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'RSpec::ExampleGroups::CPUSampling#io_intensive_operation' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 8 + expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'Object#io_intensive_operation' + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 1 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id @@ -70,7 +45,7 @@ def foo(block) expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to be_nil expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'block (4 levels) in ' expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 50 + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 25 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id @@ -85,24 +60,24 @@ def foo(block) frame = frames[3] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'baz' expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'SampleClassForTest::Sample2#baz' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 22 + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 15 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id frame = frames[4] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'bar' expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'SampleClassForTest.bar' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 28 + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 21 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 1 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id frame = frames[5] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'foo' expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'SampleClassForTest#foo' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 32 + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 25 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id @@ -110,7 +85,7 @@ def foo(block) expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to be_nil expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'block (3 levels) in ' expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 41 + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 12 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id end @@ -122,7 +97,7 @@ def foo(block) it 'should record the correct stack frames for cpu instensive operation' do expect(@messages).to have_message(Rbkit::EVENT_TYPES[:cpu_sample]) - expect(@messages).to have_most_cpu_samples_for("#{__FILE__}:17") + expect(@messages).to have_most_cpu_samples_for("#{file}:10") # Make sure stack trace is correct frames = most_frequent_sample(@messages) @@ -130,17 +105,17 @@ def foo(block) frame = frames[0] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'cpu_intensive_operation' - expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'block in RSpec::ExampleGroups::CPUSampling#cpu_intensive_operation' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 17 + expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'block in Object#cpu_intensive_operation' + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 10 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id frame = frames[1] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'cpu_intensive_operation' - expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'RSpec::ExampleGroups::CPUSampling#cpu_intensive_operation' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 16 + expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'Object#cpu_intensive_operation' + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 9 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id @@ -148,7 +123,7 @@ def foo(block) expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to be_nil expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'block (4 levels) in ' expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 121 + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 96 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id @@ -163,24 +138,24 @@ def foo(block) frame = frames[4] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'baz' expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'SampleClassForTest::Sample2#baz' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 22 + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 15 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id frame = frames[5] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'bar' expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'SampleClassForTest.bar' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 28 + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 21 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 1 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id frame = frames[6] expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to eql 'foo' expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'SampleClassForTest#foo' - expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 32 + expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql file + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 25 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id @@ -188,9 +163,22 @@ def foo(block) expect(frame[Rbkit::MESSAGE_FIELDS[:method_name]]).to be_nil expect(frame[Rbkit::MESSAGE_FIELDS[:label]]).to eql 'block (3 levels) in ' expect(frame[Rbkit::MESSAGE_FIELDS[:file]]).to eql __FILE__ - expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 41 + expect(frame[Rbkit::MESSAGE_FIELDS[:line]]).to eql 12 expect(frame[Rbkit::MESSAGE_FIELDS[:singleton_method]]).to eql 0 expect(frame[Rbkit::MESSAGE_FIELDS[:thread_id]]).to eql Thread.current.object_id end end + + describe 'when stack depth is specified' do + let(:stack_depth) { 2 } + let(:clock_type) { :wall } + let(:operation) { lambda{ io_intensive_operation } } + + it 'should record only that many number of frames as specified stack depth' do + expect(@messages).to have_message(Rbkit::EVENT_TYPES[:cpu_sample]) + + frames = most_frequent_sample(@messages) + expect(frames.size).to eql stack_depth + end + end end diff --git a/spec/support/cpu_profiling_example.rb b/spec/support/cpu_profiling_example.rb new file mode 100644 index 0000000..24aed87 --- /dev/null +++ b/spec/support/cpu_profiling_example.rb @@ -0,0 +1,28 @@ +def io_intensive_operation + r, w = IO.pipe + IO.select([r], nil, nil, 1) +ensure + r.close + w.close +end + +def cpu_intensive_operation + 100000.times{|x| Math.sqrt(x)} +end + +class SampleClassForTest + class Sample2 + def baz(block) + instance_eval 'def zab(block) block.call end' + [self, zab(block)] + end + end + + def self.bar(block) + Sample2.new.baz(block) + end + + def foo(block) + self.class.bar(block) + end +end