34

ruby-profとコアBenchmarkクラスの他に、Rubyコードのプロファイリングに何を使用しますか?特に、コードのボトルネックをどのように見つけますか?コードのどこですべての時間が費やされているかを把握するためだけに、自分の小さなツールで作業する必要があるように感じます。

ruby-profがこれを提供していることは理解していますが、出力は率直に言って非常に紛らわしく、自分のコードの実際のブロックが問題の原因であるかどうかを簡単に見つけることができません(どのメソッド呼び出しに最も時間がかかったかがわかります)けれど)。ですから、私はそれを私が望むほど多くは得られておらず、実際にそれを利用することができていません。

おそらく私はそれを間違っていますか?代替案はありますか?グーグル検索は私にとって何ももたらさない。

4

4 に答える 4

12

コードを実際に掘り下げるには、stackprofを試してください。

これを使用する方法の簡単な解決策は次のとおりです。gemをインストールしますgem install stackprof。コードに次を追加require 'stackprof'します。チェックする部分を次のように囲みます。

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

rubyスクリプトを実行した後、ターミナルの出力を次のように確認しますstackprof stackprof.dump

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 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 graphviz)を使用しdot -T pdf -o stackprof.pdf stackprof.dotて美しいPDF出力を取得します。これにより、実行に時間がかかるメソッドが強調表示されます。

于 2015-06-29T16:35:13.440 に答える
9

多くのプロファイラーはそのようなものです。あなたが知る必要があるのは、プログラムがどこで時間を費やすかではなく、その理由です。動的コード分析に関する参考資料はありますか?

追加:コードで「ボトルネック」を見つける方法は次のとおりです。(私はその言葉が嫌いです。) 理由のリストはここにあります。

「ボトルネック」を見つけるには、どういうわけか多くの測定を行う必要があると考えるのは完全に自然なことです。ほとんどすべてのプロファイラーがそれに基づいているのはとても自然なことです。

実際、発見と測定は同じ問題ではありません。あなたが見つけた(そして修正した)ものが違いを生んだかどうかを見るために測定が必要です。私にとって、何を修正するかを見つけることは、測定というよりもデバッグに似ています。

それを説明する最も簡単な方法は、無限ループまたはほぼ無限ループから始めることです。どうやって見つけますか?あなたはそれを一時停止してスタックを見ますよね?問題がスタックのどこかにあることがわかっているからです。一時停止する必要があるのは1回だけです。その後、スタック上のコードを調べる必要があります。確実に見つけたい場合は、数回一時停止してください。

コードが必要な時間の2倍しかかからないとします。つまり、一時停止すると、50%の確率で不要な処理が実行されます。一時停止して10回見ると、アクトで約5回キャッチします。実際、わずか2つのサンプルで最適化できる何かを実行しているのを見るとすぐに、「ボトルネック」が見つかります。それを修正し、スピードアップを測定し、見せびらかして、繰り返します。

あなたの最大の問題がそれほど大きくない場合でも、この方法は最終的にそれを見つけるでしょう。また、大きな問題を削除した後、小さな問題を見つけやすくなる拡大現象があります。これにより、コードがほぼ最適になるまで続行できます。

PSこれを行った後でも、スピードアップの機会があるかもしれません。たとえば、最適化アルゴリズムは数値安定性に依存する可能性があります。メッセージ駆動型アーキテクチャでは、コードが実行されている理由を追跡するのが難しくなる可能性があります。リアルタイムソフトウェアでは、パフォーマンスの問題はたまにしか発生しない可能性があり、サンプリングが簡単ではありません。これにはもっと賢さが必要です。測定だけに頼るだけではうまくいきません。

于 2010-11-03T23:49:21.743 に答える
3

これは私自身の質問ですが、プロファイリングに非常に優れたツールを見つけたので、ここに追加する必要があります。

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

フレームグラフは、バックトレースを見る場合と比較して、パフォーマンスの問題の原因を驚くほど明白にします。

于 2014-01-25T04:26:56.863 に答える
3

ruby -rprofileRubyソース内からもまたは同等に存在します。require 'profile'

ドキュメンテーション:

https://ruby-doc.org/stdlib-2.1.0/libdoc/profiler/rdoc/Profiler__.html

于 2017-07-12T18:57:33.377 に答える