Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
benchmark + profile RSpec test
require 'ruby-prof'
require 'benchmark'
module BenchmarkHelpers
PROFILE_OUTPUT_DIR = "profiling"
def self.safe_filename(name)
name.gsub(" ", "_")
end
def self.example_output_target_file!(example)
dir = File.join([ PROFILE_OUTPUT_DIR ] + example.example_group.ancestors.map { |a| BenchmarkHelpers.safe_filename(a.description) })
FileUtils.mkdir_p(dir)
File.expand_path(BenchmarkHelpers.safe_filename(example.description), dir)
end
def self.profile_example(example, options = {}, &block)
# kcachegrind output default
options = { profile_printer: RubyProf::CallTreePrinter }.merge(options)
RubyProf.start
begin
example.example_group_instance.instance_eval(&block)
ensure
result = RubyProf.stop
end
printer = options[:profile_printer].new(result)
filename = BenchmarkHelpers.example_output_target_file!(example)
file = File.new(filename + ".dat", 'w')
printer.print(file, {})
end
def self.benchmark_example(example, options = {}, &block)
Benchmark.bm(options[:label_width] || example.description.length) do |bm|
bm.report(example.description) do
example.example_group_instance.instance_eval(&block)
end
end
end
module ExampleGroupMethods
def profile(description, options = {}, &block)
benchmark_profile(description, { profile: true }.merge(options), &block)
end
def benchmark(description, options = {}, &block)
benchmark_profile(description, { benchmark: true }.merge(options), &block)
end
def benchmark_profile(description, options, &block)
proc = block
if options[:benchmark]
proc = Proc.new { BenchmarkHelpers.benchmark_example(example, options, &block) }
end
if options[:profile]
inner_proc = proc
proc = Proc.new { BenchmarkHelpers.profile_example(example, options, &inner_proc) }
end
it description, options, &proc
end
end
end
RSpec.configure do |c|
c.color_enabled = true
c.extend BenchmarkHelpers::ExampleGroupMethods
end
require 'spec_helper'
describe "benchmarks" do
def calc; (0..100).inject {|sum, n| sum + n } end
it "should calculate something" do
calc.should == 5050
end
benchmark "should benchmark" do
calc.should == 5050
end
benchmark "should benchmark and profile", profile: true do
calc.should == 5050
end
benchmark "should only profile", benchmark: false, profile: true do
calc.should == 5050
end
profile "should only profile #2" do
calc.should == 5050
end
end
[you@computer project]$ rake spec SPEC=spec/benchmark_spec.rb
/home/you/.rvm/rubies/ruby-1.9.2-p290/bin/ruby -S bundle exec rspec spec/benchmark_spec.rb
benchmarks
should calculate something
user system total real
should benchmark 0.000000 0.000000 0.000000 ( 0.000102)
should benchmark
user system total real
should benchmark and profile 0.000000 0.000000 0.000000 ( 0.000208)
should benchmark and profile
should only profile
should only profile #2
Finished in 0.01528 seconds
4 examples, 0 failures
@duckinator

This comment has been minimized.

Copy link

duckinator commented Jul 29, 2012

tack an __END__ on line 93 and I believe it can be copy/pasted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.