- NetflixがCPUヘビーなJavaマイクロサービスを m5.4xl(16 vCPU)から m5.12xl(48 vCPU)へ移行
- vCPUが3倍なので、おおよそ3倍の性能向上を期待したが、スループットは25%しか増加しない状況が発生
- しかもレイテンシは50%低下し、CPUとレイテンシのパターンはいずれも激しく「途切れる」状態(Choppy)になってしまった
- これを解決するための道のりを低レベルまで整理した記事
解決プロセス
- 高速なノードと低速なノードを比較してみることにした
- Flame Graph とJVMプロファイリング(JFR-Java Flight Recorderを活用)では違いを特定できなかった
- アプリ/OS/JVMレベルではおかしな点がなかったため、m5.12xlインスタンスが提供するPMC(Performance Monitoring Counters、PMU Counter)を調査
- 問題の1つは「False Sharing」 - 2つのコアが同じL1キャッシュラインを共有する無関係な変数を読み書きするときに生じるパターン
- JDKコードで機能は変えず、データレイアウトだけを変更するパディングバイトを挿入してこの問題を解決
- もう1つの問題は「True Sharing」 - 同じ変数を複数のスレッド/コアで読み書きすること
- これを解決するため、共有変数に書き込まず、JVMのセカンダリスーパークラスキャッシュを迂回
- この2点の両方にパッチを当てると、当初より3.5倍高速化
- この問題を解決する過程で、5年間休眠状態だったバグ JDK-8180450 の存在も判明
結論
- JVMはC++のような性能志向言語と競合できる高度に最適化されたランタイム環境だと考えられがち
- 多くのワークロードではその通りだが、特定のワークロードではアプリケーションの実装だけでなく、JVM自体の実装の影響も受けうる
- 今回のケースでは、JVMのネイティブコード内のボトルネックを見つけてパッチを当て、このワークロードのスループットを3倍以上向上させるためにPMCを活用した
- この種の性能問題については、CPUマイクロアーキテクチャレベルで実行を調べる能力が唯一の解決策となる
- Intel vTuneは、m5.12xlのようなインスタンスで公開されている主要なPMCだけでも貴重な洞察を提供する
- クラウド上のすべてのインスタンスがPEBS(Processor Event-Based Sampling)とともに包括的なPMCセットを提供すれば、より深い分析によってはるかに大きな性能向上が可能になるだろう
2件のコメント
いや、いったい……
仮説が検証されて修正できたときは、しびれるような感覚だったでしょうね。