背景
過去にいくつかpprofの使い方を紹介しましたが、実際に運用する上では以下の課題があります。
- 何かしら問題が発生して初めてプロファイリング開始するという後手になりがち
- 問題の再現が難しく、再び発生するまで様子見という流れになりがち
- プロファイリングしたことがないメンバーにとってオペレーションコストが高い
- バージョン比較ができない
これらの課題を解決するために、継続的プロファイリング(Continuous Profiling)を導入します。
環境
- Go v1.15.2
継続的プロファイリングとは
継続的にpprofのようなプロファイリングを行い、可視化も含め実運用で効果的に活用できるようにすることです。
各パブリッククラウドや監視サービスがすでにサービスとして提供しているので、自前で構築しなくてもそれらを利用できます。
ソリューション
各社が継続的プロファイリングのサポートをしています。
会社 | サービス名 |
---|---|
GCP | Cloud Profiler |
AWS | Amazon CodeGuru |
DataDog | Continuous Profiler |
OSSだとprofefeというツールがあります。
メトリクスとプロファイリングの違い
オブザーバビリティにおけるプロファイルの重要性 pprofを活用するメリットをGoogle CloudのDeveloper Advocateが語る - ログミーTech
こちらで分かりやすく説明されています。ざっとまとめると以下です
共通点
- カバーしている領域が同じ
- サンプリングする
異なる点
メトリクス | プロファイリング |
---|---|
自分で取りたいデータを定義 | あらかじめ定義されたもの (CPU, RAM, threads) |
サンプリング期間が短い | サンプリング期間が長い |
時系列データ | スタックトレースと相関のある統計データ |
導入してみる
GCPのCloud Profilerを用いて検証してみましょう。
Cloud Profilerは
- 無料
- 導入が容易
- パフォーマンス影響なし
と良いこと尽くめです。
Profiler API を有効にする
以下のコマンドで有効化してください。
$ gcloud services enable cloudprofiler.googleapis.com
コードの修正
できるだけmain関数の早い位置で以下のようにprofilerを開始してください。
func main() { cfg := profiler.Config{ Service: "my-service", // サービス名 ServiceVersion: config.BuildVersion, // バイナリビルド時にgithubのtagを埋め込む MutexProfiling: true, } if err := profiler.Start(cfg); err != nil { log.Panic("Profiler failed to start", log.Ferror(err)) } ... }
profiler.Start()
は内部でgoroutineを走らせるので、この処理はノンブロッキングです。
UI
しばらく稼働していると以下のようにWebコンソールで表示されるようになります。
CPU
メモリ
デフォルトではフレームの色は関数のパッケージに対応しています。
メモリは以下の2種類があります。
種類 | 説明 | 用途 |
---|---|---|
ヒープ | 収集時にプログラムのヒープ内に割り当てられているメモリの量 | OOMの原因となるメモリ使用箇所を特定しやすい |
割り当てられたヒープ | 収集された期間中にプログラムのヒープ内に割り当てられたすべてのメモリ。 1秒間に1MiB割り当て→1MiB解放のサイクルを10秒間繰り返すと、10MiBとして表示される |
メモリ割り当てはパフォーマンスを劣化させる。 ヒープにはないが割り当てられたヒープが高い場合は不要にアロケーションを繰り返している可能性がある。あらかじめ確保して再利用することで改善できる |
ref: https://cloud.google.com/profiler/docs/concepts-profiling
バージョン比較
Cloud Profilerではconfigに設定したバージョンを使った比較が可能です。
色については以下のように定義されています。
- 灰色: 違いがほとんどないか、まったくないことを表す
- 赤: 違いが正の値(消費が増えた)であることを表す
- 青: 違いが負の値(消費が減った)であることを表す
今回の画像を見ると少し青みがかっているので、対象としたバージョンよりも少しばかり改善されていると解釈できます。
まとめ
継続的プロファイリングの重要性、導入方法を説明しました。
ぜひ導入して定期的にチェックすることで、システムのパフォーマンス改善をしていきましょう。