React v16 Performance Inspection

React v16 がリリースされた。詳しい記事は以下のエントリを参考にすると良い。

facebook.github.io

安心と信頼の日本語版、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:

f:id:yosuke_furukawa:20170927230917p:plain

React v16:

f:id:yosuke_furukawa:20170927231110p:plain

React v15 と比較して、 React v16 だと v15 の時にあったcomponentをマウントする際の深いコールスタックが低くなり、renderingにかかるコストが改善されていることが分かる。

ブラウザのロード時間

画像が全くない純粋にJSとCSSとHTMLだけのページで計測すると次のような結果が出た(複数回実施したが大体毎回こういう計測結果だった)。

f:id:yosuke_furukawa:20170927224657p:plain

Server Side Rendering が高速化されているため、 DOMContentLoaded までの時間は短縮されているが、全体のLoadまでの時間はそれほど効果はなかった。 react-dom が v16 になり、 これまで 480KB ほどあった JavaScriptのサイズが 120KBほどに縮小されているため、もっとLoadまでの時間が速くなっても良さそうだが、弊社の環境ではJavaScriptgzipやBrotli等で圧縮されてしまっている上に、JavaScriptもCodeSplitにより分割されているので、バンドルされる1つのライブラリのサイズが4分の1になったとしても実際には誤差の範囲になってしまうようだ。

f:id:yosuke_furukawa:20170927225444p:plain

「サイズじゃなくて、 ブラウザの script 実行にかかる時間は短縮されてるのでは?」と考えてみたが、これも実際には変化はなかった。しかしクライアントのフレームグラフを見てみると、こちらもコールスタックは低くなっており、CPU使用率での改善は見込める可能性がありそうだと感じた。

React v15:

f:id:yosuke_furukawa:20170927230241p:plain

Reavt v16:

f:id:yosuke_furukawa:20170927230304p:plain

おそらく、React Fiber によってクライアントで実行するための全体的な時間は延びているものの、CPU使用率には改善が与えられるようになったのではないかと仮説を立てている。

まとめ

React v16 でどの程度性能向上が見込めるのかをひとまず計測してみた。Server Side Rendering までの時間が短縮されており、CPUコストも軽くなった。結果としてはかなり大幅な改善が見込めた。

各種React依存のライブラリのアップグレード対応は必要になるものの、migrationもそこまで大変ではなかった。

この上にまだ renderToStream やら新しく切り出された機能もあるのでそれもtryしていく予定。ひとまず本日の調査はここまで。

2017/09/29 追記: renderToNodeStreamの結果を計測したが速くなってなかった。

*1:余談だが、 この 0x と autocannon という組み合わせは Node のコンサル会社の一つであり、数多くのコアコミッターを抱える nearForm 社のメンバーが作っているコラボツール