1. ベンチマーカー
プロファイルすると、プロファイル自体に時間がかかるので正しく速度が測れない。そのためベンチマーカーも使うと良い。
ただし、ベンチマーカーはどこが遅いか等の解決の糸口は教えてくれない。
2. プロファイラ
実際に速度のボトルネックを見つける際に使う。
- stackprof
- どのメソッドに多くの時間を費やしているかがわかる
- これを入れても速度にさほど影響がない
- rblineprof
- 行ごとにかかっている時間を出してくれる
- peek-rblineprofを使うとブラウザで結果が見れる
- ただしプロファイリングに結構時間がかかる
(3. NewRelic)
実際、これらのことを手元でやらなくても、特にstackprof的なことや、どこのページやどのSQLクエリが特に遅いかなどは、 New Relic がやってくれます。お金を払うと結構詳細な部分も見れます。ここでは、これの詳細を書くのはやめてドキュメントへのリンクだけ貼っておきます。
https://docs.newrelic.com/
https://github.com/newrelic/rpm
stackprofの使い方
設定
gem 'stackprof'
して、bundle install
。
...
# Settings of StackProf
is_stackprof = ENV['ENABLE_STACKPROF'].to_i.nonzero?
stackprof_mode = (ENV['STACKPROF_MODE'] || :wall).to_sym
stackprof_interval = (ENV['STACKPROF_INTERVAL'] || 1000).to_i
stackprof_save_every = (ENV['STACKPROF_SAVE_EVERY'] || 1).to_i
stackprof_path = ENV['STACKPROF_PATH'] || 'tmp/stackprof/'
use StackProf::Middleware, enabled: is_stackprof,
mode: stackprof_mode,
raw: true,
interval: stackprof_interval,
save_every: stackprof_save_every,
path: stackprof_path
...
を追加。
この設定の後
ENABLE_STACKPROF=1 rails s
を起動し、計測したいところにアクセスする。
そうすると、pathで指定したtmp/stackprof/
以下にダンプファイルが生成される。
オプションの詳細
-
mode
: サンプリングモード.主に使われているのは,:cpu
,:wall
-
:cpu
: CPU timeとしてサンプリング -
:wall
: Wall-clock timeとしてサンプリング - RailsアプリケーションではWall-clock timeとしてプロファイリングした方がいい.(http://blog.scoutapp.com/articles/2015/09/16/profiling-rails-with-stackprof)
-
interval
: サンプリングレート.デフォルトは1000[μs] -
raw
:--flamegraph
や--stackcollapse
オプションを使う場合はtrue
-
save_every
: サンプリングの刻み -
path
: ダンプファイルが出力されるディレクトリー
プロファイリング結果を見る
stackprof [dump file(s)] # プロファイルの結果を見る
stackprof [dump file(s)] --method <メソッド名> # メソッドごとのプロファイル結果を見る
全体の結果
$ bundle exec stackprof tmp/stackprof/stackprof-wall-*.dump
Methodごとの結果
$ bundle exec stackprof tmp/stackprof/stackprof-wall-2628-1450242581.dump --method "Jpmobile::Resolver#query"
(peek-)rblineprofの使い方
設定
gem 'peek'
gem 'peek-rblineprof'
gem 'pygments.rb', require: false # Syntax highlitingが欲しい場合
して、bundle install
。
Peek.into Peek::Views::Rblineprof
#= require peek
#= require peek/views/rblineprof
@import "rblineprof"
//= require peek
//= require peek/views/rblineprof/pygments
.highlight pre {
white-space: pre;
overflow-x: scroll;
word-wrap: normal;
}
.peek-rblineprof-modal {
width: 1200px;
width: 90%;
margin-left: -45%;
}
このCSSのrequire以外の部分は、本来は必要ないはず。ただ、自分の環境では既存のCSSとコンフリクトし、各行と時間の表示位置がずれることが起きていたので改めて設定しなおした。
プロファイリングオプション
URLのパラメータでオプション指定ができる
-
lineprofiler
: プロファイリングの範囲-
app
:Rails.root/(app|lib)
以下のコード -
views
:Rails.root/app/views
以下のコード -
gems
:Rails.root/vendor/gems
以下のコード -
all
: Rails.rootのすべてのコード stdlib
-
-
lineprofiler_mode
: モード-
cpu
: CPU Timeでプロファイリング -
wall
: Wall-clock Timeでプロファイリング
-
結果の見方
http://localhost:3000/your/slow/page?lineprofiler=al&lineprofiler_mode=wall
にアクセス。以下の様な形で結果が見れる
ちなみに、lineprofiler_mode=cpu
だと、cpu timeとidle timeの2つの値が出力される
Spetial Thanks
ここに書いてあることのほとんどは、@cryeoがインターンで調べてくれました。これはその時IssueとプレゼンでまとめてくれたものをQiitaにまとめ直したものです。ありがとう!