diff --git a/harness-stats/harness.rb b/harness-stats/harness.rb index cc0a3bdd..40577ff6 100644 --- a/harness-stats/harness.rb +++ b/harness-stats/harness.rb @@ -6,8 +6,9 @@ def run_benchmark(*) frames = [] c_calls = Hash.new { 0 } - c_loops = Hash.new { 0 } + c_blocks = Hash.new { 0 } rb_calls = Hash.new { 0 } + rb_blocks = Hash.new { 0 } method_trace = TracePoint.new(:call, :c_call, :return, :c_return) do |tp| # Keep track of call frames to get the caller of :b_call @@ -31,9 +32,12 @@ def run_benchmark(*) block_trace = TracePoint.new(:b_call) do |tp| caller_event, caller_method = frames.last - # Count block calls only when the caller is a C method - if caller_event == :c_call - c_loops[caller_method] += 1 + # Count block calls + case caller_event + when :c_call + c_blocks[caller_method] += 1 + when :call + rb_blocks[caller_method] += 1 end end @@ -44,30 +48,28 @@ def run_benchmark(*) block_trace.disable method_trace.disable - c_loops_total = c_loops.sum(&:last) - c_loops = c_loops.sort_by { |_method, count| -count }.first(100) - c_loops_ratio = 100.0 * c_loops.sum(&:last) / c_loops_total - puts "Top #{c_loops.size} block calls by C methods (#{'%.1f' % c_loops_ratio}% of all #{c_loops_total} calls):" - c_loops.each do |method, count| - puts '%8d (%4.1f%%) %s' % [count, 100.0 * count / c_loops_total, method] - end - puts + show_distribution = proc do |all_counts, subject: nil, header: nil| + all_total = all_counts.sum(&:last) + top_counts = all_counts.sort_by { |_method, count| -count }.first(100) + top_ratio = 100.0 * top_counts.sum(&:last) / all_total - c_calls_total = c_calls.sum(&:last) - c_calls = c_calls.sort_by { |_method, count| -count }.first(100) - c_calls_ratio = 100.0 * c_calls.sum(&:last) / c_calls_total - puts "Top #{c_calls.size} C method calls (#{'%.1f' % c_calls_ratio}% of all #{c_calls_total} calls):" - c_calls.sort_by(&:last).reverse.first(100).each do |method, count| - puts '%8d (%4.1f%%) %s' % [count, 100.0 * count / c_calls_total, method] + puts "#{header || "Top #{top_counts.size} #{subject} (#{'%.1f' % top_ratio}% of all #{all_total} calls)"}:" + top_counts.each do |method, count| + puts '%8d (%4.1f%%) %s' % [count, 100.0 * count / all_total, method] + end + puts end - puts - rb_calls_total = rb_calls.sum(&:last) - rb_calls = rb_calls.sort_by { |_method, count| -count }.first(100) - rb_calls_ratio = 100.0 * rb_calls.sum(&:last) / rb_calls_total - puts "Top #{rb_calls.size} Ruby method calls (#{'%.1f' % rb_calls_ratio}% of all #{rb_calls_total} calls):" - rb_calls.sort_by(&:last).reverse.first(100).each do |method, count| - puts '%8d (%4.1f%%) %s' % [count, 100.0 * count / rb_calls_total, method] - end + show_distribution.call({ + 'C method calls' => c_calls.sum(&:last), + 'Ruby method calls' => rb_calls.sum(&:last), + 'block calls from C' => c_blocks.sum(&:last), + 'block calls from Ruby' => rb_blocks.sum(&:last), + }, header: 'The overall breakdown of each call type') + + show_distribution.call(c_calls, subject: 'C method calls') + show_distribution.call(rb_calls, subject: 'Ruby method calls') + show_distribution.call(c_blocks, subject: 'block calls from C') + show_distribution.call(rb_blocks, subject: 'block calls from Ruby') end }