Go言語でプロファイリング(MEMORY recyclingというよりメモリ使用状況の調査編)
前エントリーではCPU profilingを試してみましたが、今度は「Go Profiling - John Graham-Cumming」のスライドを元にMEMORY recyclingを試してみたいと思います。
※MEMORY recyclingというよりもメモリ使用状況の調査
※試してみただけでどう対応すべきかについては述べません
MEMORY recycling(メモリ使用状況の調査)
MEMORYプロファイリングはメモリリークの発見やGCの発生率を調べることができます。
まずは試してみたコードを記載しておきます。今回も検証コードはこちらの内容から利用させていただいてます。
func makeBuffer() []byte { return make([]byte, rand.Intn(5000000)+5000000) } func main() { pool := make([][]byte, 20) var m runtime.MemStats makes := 0 for { b := makeBuffer() makes += 1 i := rand.Intn(len(pool)) pool[i] = b time.Sleep(time.Second) bytes := 0 for i := 0; i < len(pool); i++ { if pool[i] != nil { bytes += len(pool[i]) } } runtime.ReadMemStats(&m) fmt.Printf("%d,%d,%d,%d,%d,%d\n", m.HeapSys, bytes, m.HeapAlloc, m.HeapIdle, m.HeapReleased, makes) } }
これはサイズが20のプールを用意しておいて、1秒毎に5000000以上10000000未満バイトのスライスを作成し、プールのいずれかの場所に格納するというサンプルです。
CPU profilingの時と同じで、プロファイリングするためには簡単ですがコードに追記する必要があります。
MEMORY recyclingの場合は、ReadMemStatsを使用します。
runtime.ReadMemStats(&m) fmt.Printf("%d,%d,%d,%d,%d,%d\n", m.HeapSys, bytes, m.HeapAlloc, m.HeapIdle, m.HeapReleased, makes)
適当なタイミングでメモリの状況を出力しておいて後ほど(リアルタイムでもできそう?)その内容を検証するという方法のようです。
以下のコマンドで実行し、適当なタイミングで終了させます。
$ go build -g garbagetest1.exe garbagetest1.go $ garbagetest1.exe > garbagetest1.dat
gnuplotで描画したグラフがこれらになります。
恐らく定期的にGCが発生しているのだと思われますが、リーク等はみられないようです。(実行時間が10分間ほどですが)
このグラフを見ながらチューニング、修正していくものと思われます。
ここから先の話はまた別のエントリーで。(いつになるか分かりませんが)
まとめ
CPU profilingにしろMEMORY recycling(メモリ使用状況の調査)にしろ、Goのデフォルトのツール(Windowsでは例外がありますが)で行えるというのは手軽で便利です。
ただプロファイルするためにオリジナルのコードに手を入れなくてはならないのがなんとも言えないところです。(コンパイル型の言語なので仕方ないです)