https://gist.github.com/wanabe/66642ae87c52f9bebf3d06a4f8c55b43 の続きで、題名の通りの作業記録です。 だいぶしつこいですがまたやります。 例によって例のごとくまったく未完成で書きながら作業しているので、いつ終わるのか何か成果が出るのかわかりません。
CRuby の MJIT は日々進歩しています。 特に、最近 r64094 で追加された "JIT compaction" は MJIT 有効時の Rails の速度改善にかなり効果が高いようです。 が、とはいえ手元だとやっぱりまだ遅い気がするので、どうなっているのか見ていきたいと思います。
例によって rails new でできた Rails アプリケーションにベンチのための変更を加えたもの https://github.com/wanabe/rails-new-benchmark で見ていきます。
こんな感じ のスクリプトを適当に作って、得られたプロットが こちら です。 だいたい 2 割強ほど遅くなっている感じでしょうか。
実行するスクリプトを小さくしてみるとどうなるか確認することにします。
ベンチマークスクリプトを 上書きするスクリプト と、その補助スクリプト を用意しました。
この状態で rm bench.log; ./bench.sh 3_000_000 などとした実行結果が こちら です。
このとき出力を見ていると 1 つも JIT されたメソッド・ブロックはなかったようなので、jit と nojit の違いは単純に誤差のみと考えられます。
本筋とはあまり関係ありませんが、単純化スクリプト と その補助スクリプト を簡単に説明します。
単純化スクリプトは、以下のものを指定して使います。
- 上書き対象のクラス
$caller_class - 上書き対象のメソッド
$caller_method_name - 環境変数
SHOWがセットされているとき- 注目するメソッドのレシーバ
$callee_receiver_name - 注目するメソッド
$callee_method_name
- 注目するメソッドのレシーバ
- 環境変数
SHOWがセットされていないとき- 単純化するときのダミーの返り値
$stub_result
- 単純化するときのダミーの返り値
たとえば、Object#call_app から呼び出される @app.get メソッドの定義を確認したいときには
$caller_class = Object / $caller_method_name = :call_app / $callee_receiver_name = "@app" / $callee_method_name = :get とした状態で SECRET_KEY_BASE="dummy" RAILS_ENV=production bundle exec rake bench_raw SHOW=1 とコマンドを実行すると、以下のような出力が得られます。
class Rack::MockRequest
def get(uri, opts={}) request(GET, uri, opts) end
end
ここから $caller_class = Rack::MockRequest / $caller_method_name = :request / $stub_result = OpenStruct.new(status: 200) として bin/rake bench_raw とコマンドを実行すると、Rack::MockRequest#request の実装を単純化した状態でベンチマークが取れる、ということです。
(OpenStruct.new(status: 200) の部分は、後続のスクリプトがエラーにならないように適当に選んでいます)
補助スクリプトは、メソッド定義の最初の行と最後の行を取得するために使っています。
こんな感じで実装の確認と単純化を交互に行っていきます。


