React v16 Performance Inspection
React v16 がリリースされた。詳しい記事は以下のエントリを参考にすると良い。
安心と信頼の日本語版、koba04記事もあるので見てみて欲しい。
React v16 changes - blog.koba04.com
さて、リリースされたので、実際に会社で作ってるSSRを実施するboilerplateに対して組み込んでみてどれだけ効果があるかを計測してみた。ただし、まだ React の renderToStream
は実施していない。ひとまずアップグレードしただけでどれだけの効果があるかを見たかったので renderToStream
の効果については今後計測予定。
2017/09/29 追記: renderToNodeStreamの結果を計測結果をまとめに追記した。
Response Benchmark
Spec: Macbook Pro 13 Processor 3.1 GHz Intel Core i5, 16 GB 2133 MHz LPDDR3
100同時接続で5秒間リクエストを集中的に送ってどれだけ捌けるか、捌いた際にどれだけのレイテンシで返ってきたかを計測した。ちなみに計測ツールは autocannon を使った。
renderするコンポーネントが数個程度の単純なページ
React v15:
Running 5s test @ http://localhost:3000 100 connections Stat Avg Stdev Max Latency (ms) 447.44 139.85 1049 Req/Sec 214 14.32 231 Bytes/Sec 22.5 MB 1.48 MB 25.2 MB 1k requests in 5s, 113 MB read
React v16:
Running 5s test @ http://localhost:3000 100 connections Stat Avg Stdev Max Latency (ms) 423.13 121.59 969 Req/Sec 227.6 8.09 237 Bytes/Sec 24 MB 839 kB 25.2 MB 1k requests in 5s, 120 MB read
大体レイテンシが 440ms(v15) => 420 ms(v16)
で 210Req/Sec(v15) => 220 Req/Sec(v16)
で多少改善されているが劇的な変化ではなかった。これはなんとなく想定通りで単純なページほど render にかかる時間がそもそも低いのでこんなもんだろうと思っていた。
render するコンポーネントが十数個以上ある複雑なページ
React v15:
Running 5s test @ http://localhost:3000/largeform 100 connections Stat Avg Stdev Max Latency (ms) 1005.66 454.75 2731 Req/Sec 88.8 5.27 94 Bytes/Sec 17.1 MB 932 kB 18.9 MB 444 requests in 5s, 85.6 MB read
React v16:
Running 5s test @ http://localhost:3000/largeform 100 connections Stat Avg Stdev Max Latency (ms) 804.6 237.79 1698 Req/Sec 114 6.79 121 Bytes/Sec 22.1 MB 1.42 MB 24.1 MB 570 requests in 5s, 109 MB read
これはアップグレードの効果が分かり、パフォーマンスの改善が見込めた。レイテンシーが平均で200ms短縮されているのと、Maxのレイテンシが落ち着いているので、パフォーマンスの振れ幅も小さくなっているのがわかると思う。 また、 Req/Seq も30程度増加しており、全体的にパフォーマンス改善傾向であることが分かる。
フレームグラフ比較
Server Side Rendering が高速化されているのは分かったので、さらに奥に入ってフレームグラフがどうなっているのかを調べてみた。これによってCPUの負荷やどこにどれだけ時間がかかっているかを粗く見ることができる。
ちなみにフレームグラフは 0x というツールで作成した*1。
React v15:
React v16:
React v15 と比較して、 React v16 だと v15 の時にあったcomponentをマウントする際の深いコールスタックが低くなり、renderingにかかるコストが改善されていることが分かる。
ブラウザのロード時間
画像が全くない純粋にJSとCSSとHTMLだけのページで計測すると次のような結果が出た(複数回実施したが大体毎回こういう計測結果だった)。
Server Side Rendering
が高速化されているため、 DOMContentLoaded
までの時間は短縮されているが、全体のLoadまでの時間はそれほど効果はなかった。 react-dom
が v16 になり、 これまで 480KB ほどあった JavaScriptのサイズが 120KBほどに縮小されているため、もっとLoadまでの時間が速くなっても良さそうだが、弊社の環境ではJavaScriptはgzipやBrotli等で圧縮されてしまっている上に、JavaScriptもCodeSplitにより分割されているので、バンドルされる1つのライブラリのサイズが4分の1になったとしても実際には誤差の範囲になってしまうようだ。
「サイズじゃなくて、 ブラウザの script 実行にかかる時間は短縮されてるのでは?」と考えてみたが、これも実際には変化はなかった。しかしクライアントのフレームグラフを見てみると、こちらもコールスタックは低くなっており、CPU使用率での改善は見込める可能性がありそうだと感じた。
React v15:
Reavt v16:
おそらく、React Fiber によってクライアントで実行するための全体的な時間は延びているものの、CPU使用率には改善が与えられるようになったのではないかと仮説を立てている。
まとめ
React v16 でどの程度性能向上が見込めるのかをひとまず計測してみた。Server Side Rendering までの時間が短縮されており、CPUコストも軽くなった。結果としてはかなり大幅な改善が見込めた。
各種React依存のライブラリのアップグレード対応は必要になるものの、migrationもそこまで大変ではなかった。
この上にまだ renderToStream
やら新しく切り出された機能もあるのでそれもtryしていく予定。ひとまず本日の調査はここまで。
2017/09/29 追記: renderToNodeStreamの結果を計測したが速くなってなかった。
React v16 で renderToString vs renderToNodeStream してみたけど全然速くなってなかった。
— Yosuke FURUKAWA (@yosuke_furukawa) 2017年9月28日
僕の実装が悪いだけかもしれんが。 pic.twitter.com/ZCpq6vZnIi
*1:余談だが、 この 0x と autocannon という組み合わせは Node のコンサル会社の一つであり、数多くのコアコミッターを抱える nearForm 社のメンバーが作っているコラボツール