Go の pprof で ボトルネックを探して ISUCON で優勝する
はじめに
pprofとは
Goで動くアプリケーションのプロファイリングを行うことができる標準パッケージです。
アプリケーション実行時におけるCPU時間などの計算資源の消費を処理ごとに計測することができます。
runtime/pprof と net/http/pprof があり、後者は前者をHTTPサーバ経由で提供してくれるパッケージです。
ISUCONの練習環境を想定しています
この記事では net/http/pprof を使ってHTTPサーバのプロファイリングを行う手順を説明します。
環境としては ISUCON の練習環境を想定しています。
ISUCONの練習環境としては、負荷をかける側のベンチマーカー用サーバと、負荷を受ける側の競技用サーバが提供されています(例: isucon/isucon12-final )。
外側からボトルネックを探す
ISUCON本 で
ボトルネックの特定は外側から順番に
藤原 俊一郎,馬場 俊彰,中西 建登,長野 雅広,金子 達哉,草野 翔. 達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践 (Japanese Edition) (p. 49). Kindle Edition.
と言われているように、Webサービスのボトルネックは外側から順番に探すと良いです。
top でWebアプリケーションのCPU利用率がボトルネックになっていそうなら、詳細な原因を特定するためにプロファイリングをしてみると良いかもしれません。
やり方
計測用のコードを仕込む
まずはGoアプリケーションに計測用のコードを仕込みましょう。
6060番ポートでプロファイリングデータが提供されるようになります。
net/http/pprof
をBlank Importするのをお忘れなく。
package main
import (
"log"
"net/http"
_ "net/http/pprof"
"runtime"
)
func main() {
runtime.SetBlockProfileRate(1)
runtime.SetMutexProfileFraction(1)
go func() {
log.Fatal(http.ListenAndServe("localhost:6060", nil))
}()
log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
次のコマンドでシュッと挿入することもできます。
go run github.com/rinchsan/ppprof/cmd/ppprof@latest -fix main.go
go run github.com/rinchsan/gosimports/cmd/gosimports@latest -w main.go
Goの静的解析は色々と便利ですね。
graphvizとgvをインストールしておく
6060番ポートで提供されるデータは人間が見やすい構造にはなっていないので、 go tool pprof
などで可視化するとよいです。
go tool pprof
で可視化するには graphviz と gv が必要になるので次のコマンドでインストールしておきましょう。
go tool pprof
を実行するサーバで必要なので、今回は競技用サーバでのインストールが必要です。
sudo apt update
sudo apt install -y gv graphviz
ベンチ開始 & プロファイリング開始
これで準備は整ったので、ベンチマーカーの走行を開始し、 go tool pprof
でプロファイリングデータの取得・可視化をしましょう。
go tool pprof
は実行開始してから終了するまでのプロファイリングデータを取得するため、ベンチの負荷走行フェーズが開始してから実行すると正確なデータを取得できます。
負荷走行フェーズは約60秒であることが多いため、 -seconds
オプションで 60
を指定して実行します。
デフォルトでは30秒になっています。
go tool pprof -seconds 60 -http=localhost:1080 http://localhost:6060/debug/pprof/profile
ローカルにポートフォワードして結果を見る
go tool pprof
のデータ取得が完了したら、可視化されたWeb UIが1080番ポートで提供されます。
競技用サーバ上でWeb UIを見るのは大変なので、ローカルマシンにポートフォワードしてWebブラウザで見ましょう。
ssh {username}@{競技用サーバのPublic IP} -fNL 1080:localhost:1080
ブラウザで http://localhost:1080 にアクセスし、例えばFrame Graphを開くと次のようなページを見ることができます。
main.(*Handler).obtainItem
あたりがCPU時間の消費としては多そうなことがわかりますね。
ファイルをダウンロードすればローカルでも見れる
Web UI上の DOWNLOAD
ボタンをクリックするとプロファイリングデータをファイルとしてダウンロードできます。
go tool pprof
を終了するとWeb UIが見れなくなってしまいますが、ファイルをダウンロードしておけば次のコマンドで再度Web UIを起動できます。
go tool pprof -http=localhost:1080 profile.pb.gz
おわりに
これで ISUCON 優勝!
※ 優勝できませんでした。
株式会社SODAの開発組織がお届けするZenn Publicationです。 是非Entrance Bookもご覧ください! → recruit.soda-inc.jp/engineer
Discussion