2011-06-12 34 views
34

我正在研究不同的優化技巧,並且我認爲採樣調用堆棧比使用探查器更有效的人遇到了這篇文章Analyzing Code for Efficiency?。其基本思想是,如果您查看調用堆棧,可以看到應用程序最可能花費大部分時間的位置,然後在那裏進行優化。如何查看ruby中調用堆棧的示例?

這當然很有趣,他顯然是這方面的專家,但我不知道如何在ruby中查看調用堆棧。在調試器中,我可以說「信息堆棧」,但似乎只顯示一行。

編輯:我看到邁克Dunlavey此評論:「我只是想指出,如果你在調試器下運行,手動打斷它,並顯示調用棧...」

我只是不確定如何手動中斷它,並減少調用堆棧。

回答

73

只要把

puts caller 

在代碼的任何地方。如果你不喜歡它的格式,它是一個字符串數組,所以你可以對所需的輸出做一些正則表達式操作。

+0

'p caller'或'puts caller.inspect'會給你一個更好的輸出格式。 – 2012-12-09 18:36:46

+4

'puts caller.join(「\ n」)'正常工作 – fotanus 2013-05-22 18:57:49

+1

不需要'.join(「\ n」)' – Nakilon 2014-04-17 23:47:42

4

您可以隨時拋出異常,然後查看[email protected]預定義變量,該變量返回一個回溯數據數組。例如。把這個foo.rb:

begin                   
    raise 'foo'                 
rescue                  
    puts [email protected]                  
end 

然後運行它:

$ ruby foo.rb 
foo.rb:2:in `<main>' 
+0

這是否在性能優化的情況下工作?如果想法是在應用程序運行緩慢的時候看到堆棧跟蹤,那麼爲了在正確的位置添加此代碼,您似乎知道瓶頸在哪裏? – d11wtq 2011-06-13 00:39:45

+0

@ d11wtq,想法是在開始和營救之間運行你的應用程序,並在應用程序運行緩慢時按Ctrl-C。這往往會導致應用程序花費大部分時間完成的事情。優化這將會使得最大的壓力。 – Mori 2011-06-13 03:17:51

+0

啊,好的,謝謝。當我在1.9.2中這樣做時。無論「begin..rescue」塊如何,我只是得到「中斷」和堆棧跟蹤。當'SIGINT'終止進程時'begin..rescue'塊在什麼地方起作用?我擔心這裏可能會有點金髮女郎o_O – d11wtq 2011-06-13 07:08:17

4

如何將信號發送到ruby進程,併爲轉儲所有堆棧的信號創建處理程序?

http://le-huy.blogspot.com/2012/04/dump-backtrace-of-all-threads-in-ruby.html我們有這個例子:

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 

然後我們需要將信號發送到相應的進程:

ps afxw | grep ruby 
kill -29 <pid> 
ls -l /tmp/ruby* 
vi /tmp/ruby_backtrace_... 

重複在適當的採樣時間的信號。

+0

也[*檢查此。*](http://stackoverflow.com/a/15280973/23771) – 2014-10-05 17:29:11

相關問題