株式会社ヘンリー エンジニアブログ

株式会社ヘンリーのエンジニアが技術情報を発信します

JVM勉強会(運用編)を開催しました

こんにちは、SREの戸田です。本日は社内で開催したJVM勉強会(運用編)の一部を公開します。

JVM、使っていますか?弊社ではサーバサイドKotlinが活躍しているので、もちろん日常的にJVMが稼働しています。このためサービス運用の一貫で必要になる知識や関連ツールなどをSREないしプロダクトチームに共有することを目的として、この勉強会を開催しました。

図1 勉強会はGoogle Meetでオンライン開催しました

パフォーマンス・チューニング

サービスを開発していると、この処理をもっと高速化したい!ランニングコストを抑えてユーザ体験の向上に投資したい!というというシーンには多く遭遇しますよね。こうしたユーザが増えてサービスに負荷がかかるようになったことで生じた課題に対して迅速に打ち手が取れることは、とても重要です。

しかし焦ってはいけません。「このコードはめっちゃループしてるし遅そう!」「あの機能を入れたら手触り悪くなったから、あの機能が怪しい!」という勘で改善を始めてしまうと、本当に改善されたのかの検証が難しいことに加え、問題の根っこを見つけられない可能性も出てきます。まずは、計測から始めましょう。

scrapbox.io

今回は問題となった処理をメソッドとして切り出せることを期待して、Java Microbenchmark Harness (JMH)を紹介しました。またその利用事例として inputStream.readBytes().toString(Charsets.UTF_8)inputStream.bufferedReader(Charsets.UTF_8).readText() に変えることで高速化することの確認を紹介しました:

Benchmark                   Mode  Cnt       Score      Error  Units
MyBenchmark.buffered128k   thrpt   25  226168.261 ± 3085.163  ops/s
MyBenchmark.buffered512k   thrpt   25  226123.470 ± 1595.982  ops/s
MyBenchmark.readBytes128k  thrpt   25    5105.985 ±   86.458  ops/s
MyBenchmark.readBytes512k  thrpt   25    1258.793 ±   49.706  ops/s

また問題が特定できていない場合に使える手段として、JDK Misson Control(JMC)などで作成できるJDK Flight Recorder(JFR)ファイルの作成を紹介しました。JFRファイルはJVMの状態をひろく、また時間軸に沿って観察したデータを残せるため、どこに問題があるかわからない状態でも活用しやすい特徴があります。

図2 JFRファイルをJMCで見ればメモリの利用状況も可視化される

そこからヒープダンプを取得したりマイクロベンチマークにつなげることで、より問題を掘り下げて調査する事ができると考えています。

起動高速化

Cloud RunでKotlinアプリケーションを動かす際、サービスの起動速度は重要なポイントになります。コンテナの起動が遅いとデプロイやスケールアウトに影響があり、最悪の場合はすぐにお客様に届けたい修正がなかなか届かない原因になってしまいます。

この課題は多くのユーザで共有されているようで、Cloud Runの公式ドキュメントではAppCDSによる高速化を紹介しています。ただこの方法だとデプロイの前処理が増えるので、スケールアウトはともかく修正を迅速に届けたい場合にはあまり有効ではないかもしれません:

cloud.google.com

今回の勉強会ではこれに加えて、CRaCjlink、native-imageについて紹介しました。またそれぞれの特徴を踏まえて、いまの自社サービスに適切と思われるアプローチについて議論しました。

図3 起動高速化に加えてコードの動作高速化についても実例を交えて議論しました

質疑応答

最後に質疑応答の時間を取りました。

まず -Xms-XX:MinRAMPercentage のような似た設定ではどちらを使えば良いのか?という質問がありました。答えは -XX:MinRAMPercentage です。JDKにはエルゴノミクスという考え方があり、ざっくりと要求を伝えておけば自身を動的に最適化してくれます。そのためヒープのサイズを -Xms-Xmx でバイト単位で指定するのではなく、このくらいまでメモリを使っていいよとざっくり伝えて細かいチューニングを任せるようにします。

docs.cloudbees.com

またStacktraceを取得するのはコストが高いのではという質問もありました。実はJava 9でStackWalkerが実装されたことで、Stacktraceを取得するコストは安くなっています。その効果は高く、例えばlog4j2ではJava9以降ではこの新しいAPIを使ってメソッド呼び出し元を特定しています。

JVMと仲良くなってKotlinをもっと活用したい

今回のJVM勉強会(運用編)は良い盛り上がりを見せました。Kotlinを活用して顧客に価値提供をするためにも、こうした基盤部分の理解を深めることは大切です。今後もチーム一丸となって学ぶため、運用編に続き開発編も開催したいと考えています。

なおKotlinに関する活動については以下の記事でも紹介していますので、あわせてご覧いただけますと幸いです。