プロファイルに基づく最適化で Go アプリケーションのパフォーマンスを向上させる
Cameron Balahan
Group Product Manager, Go Programming Language
James Ma
Sr Product Manager
※この投稿は米国時間 2024 年 7 月 9 日に、Google Cloud blog に投稿されたものの抄訳です。
2023 年に、プロファイルに基づく最適化(PGO)が Go 1.21 に導入されました。PGO を使用すると、実行時のアプリケーション プロファイルを Go コンパイラに渡すことができます。Go コンパイラはこのプロファイルに基づいて、次のビルドでコードを最適化する方法をよりスマートに判断します。
PGO は、2021 年から Google と Uber のチームが協力して構築しています。両社はコンピューティング効率を高め、費用を削減するために、さまざまな最適化を試みました。現在、Uber は PGO をフリート全体に展開し、多くのサービスで CPU 使用率を削減しています。ぜひこの続きを読み、Google Cloud 上を含む Go アプリケーションで PGO を活用する方法をご確認ください。
PGO とは
Go バイナリをビルドする際、Go コンパイラは最適化を行い、できる限り高パフォーマンスのバイナリを生成しようとします。しかし、これは必ずしも簡単な作業ではありません。多くの場合、過度にアグレッシブな最適化を行うと、かえってパフォーマンスが低下したり、ビルドに時間がかかりすぎたりするというトレードオフが生じます。コンパイラは、実行時にコードがどのように使われるかがわからないため、静的なヒューリスティックを使用して、コードでよく呼び出されるパスを推測し、それに応じて最適化を行います。
実行時にコードがどのように使われるかを、コンパイラに正確に伝えることができるとしたらどうでしょう?PGO を使えば、それが可能になります。本番環境でアプリケーションのプロファイルを収集し、次のビルドでこのプロファイルを使用すれば、コンパイラはより正確な情報に基づいて判断を下すことができます。たとえば、最も頻繁に使われる関数をよりアグレッシブに最適化したり、関数内でよく使われるケースをより正確に選択したりすることができます。
Go アプリケーションで PGO を使用する
PGO は簡単に使用できます。実行時にアプリケーションのプロファイルを収集し、次にビルドをするときに、このプロファイルをコンパイラに渡すだけです。手順は以下のとおりです。
1. プロファイルをインポートして有効にする: main パッケージで、net/http/pprof パッケージをインポートします。これにより、CPU プロファイルを取得するための /debug/pprof/profile エンドポイントがサーバーに自動的に追加されます。
2. プロファイルを収集する: 通常どおりプロジェクトをビルドし、本番環境、ステージング環境、実際的なテスト条件といった代表的な環境でアプリケーションを実行します。アプリケーションを実行し、標準的な負荷をかけながら、前の手順で作成したプロファイルをサーバー エンドポイントからダウンロードします。たとえば、アプリケーションをローカルで実行する場合は、次のようなコマンドを入力します。
3. プロファイルを使って次のビルドを最適化する: 取得したプロファイルは、次のビルドで使用できます。Go ツールチェーンは、main パッケージ ディレクトリに default.pgo という名前のプロファイルがあると、自動的に PGO を有効にします。または、go build の -pgo フラグを使って、PGO で使用するプロファイルへのパスを指定します。default.pgo ファイルはリポジトリにコミットすることをおすすめします。こうすることで、ユーザーが自動的にプロファイルにアクセスできるようになり、ビルドの再現性(と高いパフォーマンス)が保たれます。
4. 改善を測定する: 最初のプロファイルを作成した環境を再現できる場合(秒間クエリ数が一定の負荷テストなど)、最適化したビルドで新しいプロファイルを収集します。go tool pprof コマンドを使って最初のプロファイルと比較すると、CPU 使用率の減少を測定できます。
パフォーマンスの向上をベンチマークする方法について詳しくは、Go ブログのこちらの投稿をご覧ください。また、Go のドキュメントでは、PGO の内部処理や、プロファイルをより効果的に活用する方法なども学べます。
Google Cloud で Cloud Run と Cloud Profiler とともに PGO を使用する
Google Cloud ではさらに簡単に PGO を使用できます。Cloud Run を使用すると、柔軟性の非常に高い、自動化されたシンプルなコンテナ プラットフォームにアクセスできます。Go サービスはコマンド 1 つで Cloud Run に直接デプロイできます。また、サーバーレスであるため、お支払いの対象となるのは使用した分に限られます。Go サービスをデプロイした後、Cloud Profiler を有効にすると、本番環境と同様のトラフィックに対するプロファイルを収集できます。十分なデータを収集したら、プロファイルをダウンロードし、Cloud Run で Go サービスを更新します。手順は以下のとおりです。
1. Go アプリを Cloud Run にデプロイする: 最初にアプリケーションを Cloud Run にデプロイします。プロジェクトのルート ディレクトリから gcloud run deploy に --source フラグを指定して、自動的にコンパイルとデプロイを続けて行うこともできます。
デプロイが完了すると、Go サービスの実行用に固有の URL *.run.app を取得できます。
2. プロファイルを収集する: 実際的なテスト条件でアプリケーションを実行します。アプリケーションを実行し、標準的な負荷をかけながら、Cloud Profiler からプロファイルを収集してダウンロードします。
3. プロファイルを使用して次のビルドを最適化する: 先ほどと同様に、前の手順でダウンロードしたプロファイルの名前を default.pgo に変更して、プロジェクトの main パッケージ ディレクトリに移すことで、PGO を有効にします。
4. 改善を測定する: Cloud Run の指標ダッシュボードを使用して、課金対象のコンテナ インスタンス時間とコンテナの CPU 使用率の改善をモニタリングします。
その他のリソース
Google Cloud を使い始めたばかりの方や、アプリケーションで Google Cloud ソリューションを活用する方法について詳しく知りたい方には、こちらのクイックスタートで、Cloud Run に Go サービスをデプロイする方法を説明しています。さらに深く学びたい方は、以下のコースとガイド付きラボをご確認ください。
-
Cloud Build と Firebase のパイプラインを使用して Hugo ウェブサイトをデプロイする: 一般的なオープンソースの静的サイト生成ツール Hugo(Go で作成)を、Firebase や Cloud Build とともに使用する方法を学びます。
-
Manage Kubernetes in Google Cloud: Kubernetes Engine クラスタを構築し、kubectl で管理する方法など、GKE のすべてを学びます。
Google Cloud Innovators に無料で登録すると、こうしたラボの受講などに使用できる 35 個のクレジットが毎月付与されます。クラウドやクラウドベースのアプリケーションに関する最新スキルの習得にお役立てください。
これで完了です。Go は継続的に PGO の改良に取り組んでいるため、リリースごとにアプリケーションのパフォーマンスが向上します。プロジェクト、負荷、実行時の条件が変わった場合は、必ず新しいプロファイルを作成し、default.pgo をソース管理に最大限に活用してください。