ruby debugging: print line number when taking too long
benchmarking, profiling, ruby
Solution
require 'timeout'
def do_something
Timeout::timeout(9) do
sleep 10
end
rescue Timeout::Error => e
puts "Something near line #{__LINE__} is taking too long!"
# or, count backwards in method
puts "Line #{__LINE__ - 5} is taking too long!"
end
do_something
This will stop execution if the timeout block runs out of time and raise a Timeout error. If you want to continue execution, you might do better with benchmark:
require 'benchmark'
time = Benchmark.realtime do
sleep 10
end
puts "Line #{__LINE__ - 2} is slow" if time > 9
One benchmark block can have multiple timers:
Benchmark.bm do |b|
b.report('sleeping:') { sleep 3 }
b.report('chomping:') { " I eat whitespace ".chomp }
end
See more about benchmark here: http://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html
If you want to keep track of the line number being executed, why don't you try passing it in to a custom method like so:
def timethis(line, &block)
if Benchmark.realtime(&block) > 2
puts "Line #{line} is slow"
end
end
timethis(__LINE__) { sleep 1 }
Problem
Is there a way in Ruby to have it print the `__LINE__` number of code (at my script level, not required gems) it's working on if taking longer than 9 seconds (adjustable)? For debugging I am getting it to print verbose output of what it's trying to do, where it is in the code etc., rather than silently sitting for long periods of time. A flaky situation makes it unpredicable how far it gets before something times out, so successive advancing doesn't apply here. EDIT Something like a trap would work, such that: - The original line number and hopefully code get remembered (both benchmark and timeout gems lose track of `__LINE__` for instance.... Maybe there is a way to push it off to another .rb file to manipulate the stack to include my file & line of interest?) - When the overtime warning prints, execution still continues as if nothing had changed.