プロファイラを活用することで、プログラムの実行速度や使用リソースの収集ができます。そして、プロファイル結果を解析することでコードのボトルネックを把握し、プログラムのパフォーマンスチューニングを効率的に実施できます。
プロファイラとは何か
プロファイラとは、プログラムの実行時にパフォーマンス情報を収集するツールです。プログラムの各部分の実行時間や、使用リソースなどを詳細に解析できます。プロファイラを使用することで、パフォーマンス上のボトルネックを特定し、最適化を行うことができます。
プロファイラには主に、実行速度の最適化とリソース使用量の最適化のケースで利用されます。
- 実行速度の最適化では、プログラムの各部分がどの程度の時間を要しているかを確認することで、チューニングが必要な箇所を特定します。
- リソース使用量の最適化では、オブジェクトの割り当てやメモリ使用量など、リソースの利用状況を分析し、リソース使用量の最適化をはかることができます。
Rubyのプロファイリングをするgem
Rubyの主要なプロファイリングを行うgemにはいくつかあります。
名前 | star (23/4) | 説明 |
---|---|---|
ruby-prof | 2k | Rubyプログラムの実行速度をプロファイルする高速なコードプロファイラ。 多様なレポート形式や、グラフ表示が可能 |
stackprof | 2k | サンプリングしたコールスタックのプロファイラ。 |
rack-mini-profiler | 3.5k | HTMLにプロファイル結果を表示するプロファイラ |
他にも、メモリ消費やガベージコレクタの動作を詳細に分析できる memory_profiler やRSpecやFactoryBotなどテストをプロファイルできる test-prof などがあります。
ruby-profの使い方
gemのインストール
gem 'ruby-prof'
Rackアプリケーションへの設定方法
require 'ruby-prof' # 計測方法(経過時間、プロセス時間、オブジェクト割り当て、メモリを測定できる) RubyProf.measure_mode = RubyProf::WALL_TIME # Rackアプリケーションで特定のパスをプロファイル use Rack::RubyProf, path: 'tmp/ruby-prof', only_paths: [%r{/api/v1/users}]
レポート形式はテキスト、HTML、グラフなどいろいろある。
詳細の使い方は ruby-prof を確認
stackprofの使い方
gemのインストール
gem 'stackprof'
Rackアプリケーションへの設定方法
require 'stackprof' mode = :wall # cpu, object, custom などできる use StackProf::Middleware, enabled: true, mode:, interval: 1000, save_every: 5, # raw: true, path: "tmp/stackprof-#{mode}-myapp.dump"
dumpファイルをstackprof
コマンドで解析する
stackprof tmp/stackprof-cpu-*.dump --text --limit 10 ================================== Mode: cpu(1000) Samples: 17 (34.62% miss rate) GC: 1 (5.88%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 7 (41.2%) 7 (41.2%) MyApp#do_slow_stuff 3 (17.6%) 3 (17.6%) IO#set_encoding 6 (35.3%) 3 (17.6%) Kernel#require 1 (5.9%) 1 (5.9%) (marking) 1 (5.9%) 1 (5.9%) Mysql2::Client#connect 1 (5.9%) 1 (5.9%) Mysql2::Client#_query 1 (5.9%) 1 (5.9%) Hash#delete 16 (94.1%) 0 (0.0%) Sinatra::Base#invoke 16 (94.1%) 0 (0.0%) Sinatra::Base#call! 16 (94.1%) 0 (0.0%) Sinatra::Base#call
コードのどの部分が遅いかもみれる
stackprof tmp/stackprof-wall-*.dump --text -m --file app.rb | 103 | get '/api/v1/users' do 10 (4.0%) | 104 | users = select_users | 105 | 233 (92.1%) | 106 | do_slow_stuff | 107 | 6 (2.4%) | 108 | json(status: true, data: { users: }) | 109 | end | 110 | | 111 | def select_users | 112 | users = [] | 113 | 10 (4.0%) | 114 | mysql_db.query('SELECT id, name FROM users').each do |row| | 115 | users.push({ | 116 | id: row[:id], | 117 | name: row[:name], | 118 | }) | 119 | end | 120 | end | 121 | | 122 | def do_slow_stuff 233 (92.1%) | 123 | 1_000_000.times.each do |n| | 124 | n + 1 233 (92.1%) / 233 (92.1%) | 125 | end
詳細な使い方は GitHub - tmm1/stackprof: a sampling call-stack profiler for ruby 2.2+ を確認
rack-mini-profilerの特徴
gemのインストール
gem 'rack-mini-profiler'
Rackアプリケーションに設定
require 'rack-mini-profiler' use Rack::MiniProfiler
HTMLの画面に表示される
参考: プロファイル結果の出力例の対象コード
上記のプロファイルの出力結果のコード
get '/api/v1/users' do users = select_users do_slow_stuff json(status: true, data: { users: }) end def select_users users = [] mysql_db.query('SELECT id, name FROM users').each do |row| users.push({ id: row[:id], name: row[:name], }) end end def do_slow_stuff 1_000_000.times.each do |n| n + 1 end end