Amazon Web Services ブログ
CodeGuru Profilerを用いたAmazonのアプリケーションのCPUとレイテンシーのパフォーマンス改善
(この記事は、 Improving the CPU and latency performance of Amazon applications using Amazon CodeGuru Profiler を翻訳したものです。)
Amazon CodeGuru Profiler は機械学習を活用し、アプリケーションコードのボトルネックになっている部分の特定をサポートし、最適化のための推奨事項を提供してくれるデベロッパー用ツールです。Amazon CodeGuru Profilerを用いることによってアプリケーションのパフォーマンスの問題の特定、レイテンシーやCPU使用効率の問題を解決することができます。
CodeGuru Profilerは AWS Lambda, Amazon Elastic Compure Cloud (Amazon EC2), Amazon Elastic Container Service (Amazon ECS),Amazon Elastic Kubernetes Service (Amazon EKS), AWS Fargate, AWS Elastic Beanstalk, およびオンプレミスで稼働しているアプリケーションのパフォーマンスの問題解決に役立ちます。
本ブログではAmazonのリテールサービスが、どのようにCodeGuru Profilerを用いてCPUの使用率とレイテンシーを50%減らし、$100,000のコストを削減したかの大まかな概要について解説します。
CodeGuru Profilerの技術面、ビジネス面での価値とは
CodeGuru Profilerは簡単で使いやすいツールです。CodeGuru Profilerをバックグラウンドで実行させ、CodeGuru Profilerを通して発見された問題点を修正することによってパフォーマンスを改善させることができます。
CPUやRAMを多く消費する従来のプロファイリングツールと異なり、CodeGuru Profilerのアプリケーションに与えるCPUのオーバーヘッドは1%未満であり、通常100MB以下のメモリしか使用しません。
テスト環境でCodeGuru Profilerを実行して問題を特定、変更をテストし、この変更がアプリケーションに悪影響を与えないことを確認できます。
CodeGuru Profilerは高いCPU使用率やレイテンシーの問題を自動的に特定します。また可視化ツールを提供しどのようにパフォーマンスの問題を解決するかを示し、問題のコードを実行した際のコストについて提示します。これによって早期に異常を発見し本番環境での問題発生を防ぐことができます。早期に問題を特定しカスタマーエクスペリエンスに影響を与える前に十分な修正までの時間を得られることはお客様の問題解決の修正の優先順位付けに役立ちます。
Amazon でのCodeGuru Profiler の活用事例
Amazonでは数多くのアプリケーションにCodeGuru Profilerが適用され、その結果数百万ドルものコスト削減とレイテンシーの改善を実現しています。このブログではAmazon Prime においてどのようにCodeGuru Profilerを利用し、少しのコード変更で$100,000を節約した事例についてご紹介します。
CodeGuru Profilerを利用した改善の詳細
私たちがある一つのデータのペイロードのサイズが増加する変更を加えてしまったとき、予想よりもサービスのレイテンシーへの影響が顕著でした。しかしCodeGuru Profilerを利用して本番環境で実行するための修正を素早く実装しデプロイすることができました。
Amazon CodeGuru Profilerを適用した後、視覚化されたパフォーマンスの分析結果からCPUの処理時間の大部分がJacksonのデシリアサイズの処理によって占められていることを特定しました。(2つのコールによって37%利用) また以前私たちが実施したパフォーマンステストにて通常時のCPU負荷をかけている際、パフォーマンスの低下が見られたのですが(下記のグラフの青い部分)、興味深いことに大半のブロッキング処理がJacksonのデシリアライズの部分で発生していました。
フレームグラフは、CPUがコールグラフの各ポイントで費やす相対的な時間を表します。幅が広いほど、対応するCPU使用率が高くなります。下記はパフォーマンス改善の修正を入れる前のコードのフレームグラフとなっております。
以下のグラフはパフォーマンス改善を実施する前のフレームグラフです。
(デプロイ前のフレームグラフ)
Jacksonのソースの_createAndCacheValueDeserializer
の部分を確認してみるとそこにはsynchronizedブロックがありました。その中では_createAndCache2
が呼び出されていて、その関数がキャッシュに要素を追加していました。キャッシュに存在しないシリアライザのキャッシュはこの関数内で作成されていましたがここに問題がありました。CodeGuruのフレームグラフは私たちが作った型のカスタムシリアライザの生成にともなうリフレクションでCPUが多く消費されている事を示していました。コード内のコメントが指し示すようにisCachable()
がオーバーライドされてtrue
を返す場合にのみカスタムシリアライザのキャッシュを追加する実装になっておりキャッシュが生成されていなかったのです。
どう修正したか
私たちはisCachable()
の仕様を確認し、オーバーライドによる方法が今回のパフォーマンスの問題に対して正しい解決方法かを確認しました。そして私たちがisCachable()
に変更を加えたリリースをした後、_createAndCacheValueDeserializer
によって起こっていたパフォーマンスの問題は解決しました。
上記の調査と修正の結果
シリアライザのキャッシュが効くことによりリクエスト毎の処理時間は以前の半分の時間で処理されるようになりました。また同じデシリアライザのキャッシュ生成に伴うロックを保持しなくて良くなったため、より効率的なCPUの利用を可能にしました。デシリアライザの再利用によって不要な処理を回避し、リソースの節約が可能になったのです。
CodeGuru Profilerが指し示してくれた部分を修正することによりJacksonによって利用されていたCPU利用率を37%から5%に削減することができました。このサービスは大部分のリクエストで他のサービスを呼び出すこともなかったのでレイテンシーもほぼ同じ量削減されました。さらに嬉しいことに全ての呼び出しの際に、同じデシリアライザの作成にともなうロックがなくなったためレイテンシーの低下を招くことなく、より効果的にCPUを使えるようになりました。この結果サービスのトラフィックは4倍になった場合でも、Amazon EC2のフリートのサイズを削減できAmazon EC2のコストを$100,000削減できたのです。
以下は修正リリース後のフレームグラフです。
(修正後のフレームグラフ)
修正後のメトリクス
下記のグラフはCPUの使用率が50%に減ったことを示しています。青い線がCodeGuru Profilerによって指摘された問題点を修正する前のグラフになっています。そして緑の線がデプロイ後のCPU使用率であり下がっていることがわかります。私たちはパフォーマンスを向上させながら安全にコスト削減をすることができたのです。
(修正後のフレームグラフ)
修正後のメトリクス
下記のグラフはCPUの使用率が50%に減ったことを示しています。青い線がCodeGuru Profilerによって指摘された問題点を修正する前のグラフになっています。そして緑の線がデプロイ後のCPU使用率であり下がっていることがわかります。私たちはパフォーマンスを向上させながら安全にコスト削減をすることができたのです。
以下のグラフはサーバーのレイテンシになっておりほぼ50%下がっていることがわかります。グラフの左端の部分が示すように、レイテンシーは100msから50msに減少しました。オレンジ色の線はパーセンタイル99、緑色の線はパーセンタイル99.9、青色の線はパーセンタイル50を示しています(レイテンシーを意味しています)
まとめ
少しのコードの変更と30分の調査で私たちはボトルネックを取り除きそれによって負荷が下がりEC2のコストを減らすことができました。CodeGuru ProfilerはAmazonの様々なチームで利用されており、その結果として数百万ドルの節約とパフォーマンスの最適化をもたらしました。CodeGuru Profilerを利用することによってあなたは素早くあなたのアプリケーションの問題点を発見できます。コードとアプリケーションの効率が高いほど実行にかかるコストは低くなります。CodeGuru Profilerを使用することによって、本番環境で実行されているアプリケーションの潜在的な無駄を見つけ、インフラストラクチャーにかかるコストを大幅に削減することができます。
翻訳はソリューションアーキテクト、紙谷が担当しました。原文はこちらです。