Railsアプリ パフォーマンス比較の方法
どうも、igutoです。
ここ最近、Railsアプリのパフォーマンス改善を担当しています。 パフォーマンス改善のためのコードを書いた後には、改善した箇所についてどれくらい改善できたかを確認したいものです。確認の方法について幾つか試行錯誤して、自分が納得できるものを見つけたので、紹介します。
以前までの方法
以前は、 ブラウザからリクエストを何度も送り、rack-mini-profiler
の表示から時間を手でメモして、平均を出す…なんていうことしていました。
この方法では、平均や改善度合いなどを自分で計算しなければなりません。小さな変更を確認するにも、1ページ全体をリクエストし、そのレスポンスを待つ必要があります。
紹介する方法
Rails runner
と benchmark-ips
を使います。
Rails runner
Rails runnerは、Railsアプリの一部の処理だけを呼び出すことができるコマンドです。
$ bundle exec rails runner --help Usage: rails runner [options] [<'Some.ruby(code)'> | <filename.rb>] -e, --environment=name Specifies the environment for the runner to operate under (test/development/production). Default: development -h, --help Show this help message. Examples: rails runner 'puts Rails.env' This runs the code `puts Rails.env` after loading the app rails runner path/to/filename.rb This runs the Ruby file located at `path/to/filename.rb` after loading the app You can also use runner as a shebang line for your executables: ------------------------------------------------------------- #!/usr/bin/env /home/centos/rubymine_projects/ishin-openboard/bin/rails runner Product.all.each { |p| p.price *= 2 ; p.save! } -------------------------------------------------------------
helpにあるように文字列として指定したコードや、ファイルに書いた内容を実行することもできます。 例えばこんな感じで使えます。
$ bundle exec rails runner 'p User.all.class' User::ActiveRecord_Relation
benchmark-ips
https://github.com/evanphx/benchmark-ips
時間あたりの実行回数を基に処理速度を算出してくれるベンチマークライブラリ。 実行回数調整のための試行錯誤が必要無い上に、複数ベンチマーク対象を指定した場合は勝手に速度比較までしてくれます。
require 'benchmark/ips' Benchmark.ips do |r| r.report("plus") do 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 end r.report("multi") do 1 * 10 end r. compare! end
上のコードを実行すると、ベンチマーク結果として次のような出力が得られます。
Warming up -------------------------------------- plus 137.714k i/100ms multi 152.615k i/100ms Calculating ------------------------------------- plus 5.490M (± 1.0%) i/s - 27.543M in 5.017803s multi 9.475M (± 1.1%) i/s - 47.463M in 5.009965s Comparison: multi: 9474980.2 i/s plus: 5489593.4 i/s - 1.73x slower
Rails runnner + benchmark-ips
これら2つを合わせて…。下のようなスクリプトを書き、bundle exec rails runner <script path>
で実行すれば、毎回毎回ブラウザからページ呼び出しをせずに、改善箇所だけのパフォーマンス改善の確認ができます!
require 'benchmark/ips' Benchmark.ips do |r| customers = Customer.includes(:customer_items).all.take(1000) r.report 'normal' do customers.each do |customer| customer.customer_phases.map(&:scheme) end end r.report 'cache' do customers.each do |customer| customer.customer_phases.map(&:scheme_with_cache) end end r.compare! end
おわりに
Railsアプリの一部だけのパフォーマンスの改善量を手軽に測る方法を紹介しました。 これを使うようになってからブラウザの操作や手動での結果確認、計算の手間をなくすことができ作業が快適になりました!