2010-11-03 74 views
19

除了ruby-prof和核心Benchmark類之外,您用什麼來分析Ruby代碼?特別是,你如何找到代碼中的瓶頸?它幾乎感覺我需要使用我自己的小工具來確定所有時間都花在我的代碼中。剖析Ruby代碼

我意識到ruby-prof提供了這個功能,但是輸出結果非常混亂,並且很難找出你自己的代碼的哪個塊是問題的根源(它告訴你關於哪個方法調用盡管花了大部分時間)。所以我並沒有真正想要那麼多,也沒有真正能夠利用它。

也許我做錯了嗎?有替代品嗎?谷歌搜索不會爲我提供任何東西。

+1

你有,我不得不在同樣的問題[是否有可能在profiling的時候忽略不相關的方法紅寶石應用程序?](http://stackoverflow.com/questions/2241491/is-it-possible-to-ignore-irrelevant-methods-when-profiling-ruby-applications)。我發現了關於ruby-prof的方法消除選項。 – 2010-11-04 02:44:30

回答

6

很多輪廓儀都是這樣的。 你需要知道的不是其中該程序花費的時間,但爲什麼Any references on Dynamic Code Analysis?

ADDED:Here's how我在代碼中發現「瓶頸」。 (我討厭這個詞。) Here's a list的原因。

假設要找到「瓶頸」,你必須以某種方式進行大量測量是非常自然的。 幾乎所有的剖析器都基於它,這是很自然的。

實際上,查找和測量不是同一個問題。測量是需要看看你發現(和固定)是否有所不同。對我而言,尋找解決辦法更像調試而非測量。

解釋它最簡單的方法是從無限循環或接近無限循環開始。你是怎麼找到它的?你暫停它,看看堆棧,對吧?因爲你知道問題在堆棧中的某處。您只需暫停一次,然後您需要研究堆棧中的代碼。如果你想確定你找到它,暫停幾次。

假設代碼只需要兩倍的時間。這意味着當你暫停時,有50%的機會會看到它做不必要的事情。如果你暫停一下並觀察它10次,你會在大約5次的動作中捕捉到它。事實上,只要你看到它做了一些你可以優化的樣本少至2個,你就發現了一個「瓶頸」。修復它,測量加速,顯示它並重復。

即使你最大的問題不是很大,這個方法最終會找到它。 此外,還有一個放大現象,在刪除較大問題後,小問題變得更容易找到。這可以讓你繼續下去,直到代碼接近最佳。

P.S.完成此操作後,可能仍有機會加速。例如,優化算法可能取決於數值穩定性。消息驅動體系結構可能會使跟蹤代碼執行的原因變得更加困難。在實時軟件中,性能問題可能只是偶爾發生,並且不太容易採樣。這需要更聰明。重新開始測量並沒有做到這一點。

+1

謝謝你,我會嘗試這種方法。我剛剛也發現了perftools,它是一個採樣分析器,並生成如下圖所示的調用圖:http://perftools-rb.rubyforge.org/examples/rubygems.gif - 您是否認爲要手動完成一些額外的信息真的提供了很多優勢嗎? – ehsanul 2010-11-04 18:19:58

+0

@ehsanul:絕對如Gprof替代方法鏈接的第3點所述。但不要只聽到我的話:http://stackoverflow.com/questions/2624667/whats-a-very-easy-c-profiler-vc/2624725#2624725 http://stackoverflow.com/questions/ 2473666/tips-for-optimize-c-net-programs/2474118#2474118這就像比較華麗的汽車到一架醜陋的飛機。一個看起來不錯,但另一個讓你在那裏。 – 2010-11-04 20:25:34

+0

@MikeDunlavey:一個tyro的問題:你如何中斷一個ruby應用並獲得回溯?你可以捕獲SIGINT進入ruby調試器嗎?或者你在gdb下做了什麼? – 2013-03-07 16:03:15

2

這是我自己的問題,但我發現了一個工具,它是如此驚人的分析,我要在這裏添加:

http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler

Flamegraphs使性能問題的根源驚人明顯,相對看回溯。

+1

我承認看回溯是乏味和醜陋的,火焰圖是性感的,但與火焰圖相比,回溯會找到加速的超集。 [*這是爲什麼。*](http://stackoverflow.com/a/27867426/23771) – 2015-06-30 13:33:44

5

要深入瞭解您的代碼,請嘗試使用stackprof

下面是如何使用它的快速解決方案: 安裝gem:gem install stackprof。在你的代碼添加:require 'stackprof'和環繞要檢查這個部分:

Mode: cpu(1000) 
Samples: 9145 (1.25% miss rate) 
GC: 448 (4.90%) 

TOTAL (pct)  SAMPLES (pct)  FRAME 
    236 (2.6%)   231 (2.5%)  String#blank? 
    546 (6.0%)   216 (2.4%)  ActiveRecord::ConnectionAdapters::Mysql2Adapter#select 
    212 (2.3%)   199 (2.2%)  Mysql2::Client#query_with_timing 
    190 (2.1%)   155 (1.7%)  ERB::Util#html_escape`` 

這裏:

StackProf.run(mode: :cpu, out: 'stackprof-output.dump') do {YOUR_CODE} end

運行你的Ruby腳本去檢查終端的輸出與stackprof stackprof.dump後你可以看到你需要很多時間的所有方法。現在真棒部分:鑽只是做stackprof stackprof.dump --method String#blank?,你會得到具體方法的輸出:

String#blank? (lib/active_support/core_ext/object/blank.rb:80) 
    samples: 231 self (2.5%)/ 236 total (2.6%) 
    callers: 
    112 ( 47.5%) Object#present? 
    code: 
            | 80 | def blank? 
    187 (2.0%)/ 187 (2.0%) | 81 |  self !~ /[^[:space:]]/ 
            | 82 | end 

而且你可以很容易地計算出你的代碼的一部分,需要大量的時間來運行。

如果你想獲得一個視覺輸出做stackprof stackprof.dump --graphviz >> stackprof.dot和使用的graphviz(brew install graphvizdot- T pdf -o stackprof.pdf stackprof.dot得到一個漂亮的PDF輸出,這強調了需要很長的時間來運行的方法。