Ruby on RailsのN+1 partial renderingのパフォーマンス悪化を測定してみました。

環境

Ruby 2.4.1
Rails 5.1.1
DB MySQL
OS macOS Sierra

計測用のコード

コントローラ

N+1パーシャルレンダリングのビューファイル

コレクションを使ったレンダリングのビューファイル

計測方法

peek-rblineprofで行レベルで計測しつつ、stackprofでメソッドごとの負荷を確認。また、Railsの環境はdevelopmentで動かしています。production環境だと今回の計測結果よりかなり早くなるようです。

結果

1000回のパーシャルレンダリングのラインプロファイルの結果は以下になります。renderの部分がボトルネックになっています。

viewファイルを見るとパーシャルレンダリングで時間がかかっています

ブロックの処理自体にはそこまで時間がかかっていません

実際どの程度パフォーマンスを悪化させるのかを見るためにパーシャルレンダリングの回数とパフォーマンスについて調査しました。

回数 CPU time + (wall time – CPU time)
10 15.6ms +      9.8ms
100 177.1ms +    166.6ms
1,000 1622.2ms +   1473.2ms
10,000 13625.4ms +  13337.2ms
10,000 (コレクション) 172.3ms +     61.8ms

100回を越えるとパフォーマンス的に厳しくなってきます。

1000回のパーシャルレンダリング時のstackprofの結果は以下のとおり

ActionView::PathResolver#find_template_pathsやActionView::PathResolver#queryでかなり時間を使っていることがわかります。

参考URL