How do you view a sample of the call stack in ruby?

前端 未结 3 1624
一整个雨季
一整个雨季 2020-12-28 12:01

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

相关标签:
3条回答
  • 2020-12-28 12:32

    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.

    0 讨论(0)
  • 2020-12-28 12:40

    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.

    0 讨论(0)
  • 2020-12-28 12:45

    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>'
    
    0 讨论(0)
提交回复
热议问题