Skip to content

Instantly share code, notes, and snippets.

@eregon
Last active September 19, 2020 14:07
Show Gist options
  • Save eregon/eb2892005799c0cf82ced16e2e065b5c to your computer and use it in GitHub Desktop.
Save eregon/eb2892005799c0cf82ced16e2e065b5c to your computer and use it in GitHub Desktop.
benchmark block - a prototype to benchmark a block without the block overhead
#!/usr/bin/env ruby
private def benchmark(name = nil, &block)
raise "needs a block" unless block
binding = block.binding
file, line = block.source_location
start_line = line - 1
lines = File.readlines(file)
indent = lines.fetch(start_line)[/^(\s+)/, 1]
end_line = start_line + 1
until lines[end_line] =~ /^#{indent}end/
unless lines[end_line] =~ /^#{indent}/
raise "Line #{end_line+1} doesn't start with #{indent.inspect}: #{lines[end_line].inspect}"
end
end_line += 1
end
code = lines[start_line+1...end_line].join("\n").strip
unless name
vars = binding.local_variables.select { |var| code =~ /\b#{Regexp.escape var}\b/ }
if vars.empty?
name = code
else
pairs = vars.map { |var| [var, binding.local_variable_get(var).inspect] }.to_h
# name = "#{code} with #{pairs.map { |k,v| "#{k}=#{v}" }.join(", ")}"
name = code
pairs.each_pair do |var, value|
name = name.gsub(/\b#{Regexp.escape var}\b/, value)
end
end
end
STDOUT.print "#{name} "
STDOUT.flush
timings = binding.eval <<-RUBY
i = 0
timings = []
while i < 5 # TODO warmup, inner loop, etc
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
#{code}
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
timings << (t1 - t0)
i += 1
end
timings
RUBY
avg = timings.sum / timings.size
ips = 1.0 / avg
STDOUT.puts "#{"%.3f" % ips} i/s (#{"%.3f" % avg}s/i)"
end
ARGV.each { |arg| Kernel.load(arg) }
def fib n
if n < 3
1
else
fib(n-1) + fib(n-2)
end
end
(28..32).each do |n|
benchmark do
fib(n)
end
end
$ ./benchmark-block fib.rb
fib(28) 72.505 i/s (0.014s/i)
fib(29) 44.902 i/s (0.022s/i)
fib(30) 27.826 i/s (0.036s/i)
fib(31) 17.258 i/s (0.058s/i)
fib(32) 10.591 i/s (0.094s/i)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment