I'm investigating different optimization techniques, and I came across this post Analyzing Code for Efficiency? by someone who believes that sampling the call stack is more effective than using a profiler. The basic idea is that if you take a view of the call stack, you see where your application is most likely to be spending most of its time, and then optimize there.
It is certainly interesting, and he is obviously an expert on this, but I don't know how to view the call stack in ruby. In debugger I can say "info stack" but only seems to show one line.
EDIT: I saw this comment by Mike Dunlavey: "I would just like to point out that if you run under the debugger, interrupt it manually, and display the call stack..."
I'm just not sure how to interrupt it manually and dipslay the call stack.
While debugging, in the Debug menu, select Windows > Call Stack or press ctrl + alt + C . A yellow arrow identifies the stack frame where the execution pointer is currently located. By default, this stack frame's information appears in the source, Locals, Autos, Watch, and Disassembly windows.
Whenever you call a method, Ruby places a stack frame on the call stack (or "runtime stack", but often just called "stack"). The stack frame is a memory allocation that holds the method's arguments, some space for internal variables, and the return address of the caller.
The call stack is a list of all the active functions that have been called to get to the current point of execution. The call stack includes an entry for each function called, as well as which line of code will be returned to when the function returns.
In computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, program stack, control stack, run-time stack, or machine stack, and is often shortened to just "the stack".
Just put
puts caller
anywhere in the code. If you don't like its format, it's an array of strings, so you can do some regex manipulation for a desired output.
How about sending signal to the ruby process, and creating a handler for the signal which dumps all stacks?
From http://le-huy.blogspot.com/2012/04/dump-backtrace-of-all-threads-in-ruby.html we have this example :
require 'pp' def backtrace_for_all_threads(signame) File.open("/tmp/ruby_backtrace_#{Process.pid}.txt","a") do |f| f.puts "--- got signal #{signame}, dump backtrace for all threads at #{Time.now}" if Thread.current.respond_to?(:backtrace) Thread.list.each do |t| f.puts t.inspect PP.pp(t.backtrace.delete_if {|frame| frame =~ /^#{File.expand_path(__FILE__)}/}, f) # remove frames resulting from calling this method end else PP.pp(caller.delete_if {|frame| frame =~ /^#{File.expand_path(__FILE__)}/}, f) # remove frames resulting from calling this method end end end Signal.trap(29) do backtrace_for_all_threads("INFO") end
Then we need to send the signal to the appropriate process :
ps afxw | grep ruby kill -29 <pid> ls -l /tmp/ruby* vi /tmp/ruby_backtrace_...
Repeat the signal at appropriate sampling time.
You can throw an exception at any time, and then look at the $@
predefined variable, which returns an array of backtrace data. E.g. put this in foo.rb:
begin
raise 'foo'
rescue
puts $@
end
Then run it:
$ ruby foo.rb
foo.rb:2:in `<main>'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With