Go Wiki: CustomPprofProfiles

元々はhttps://rakyll.org/custom-profiles/で公開されました。


Goは、Goプログラムからプロファイリングデータを収集するために、すぐに使用できるいくつかのpprofプロファイルを提供しています。

runtime/pprofパッケージによって提供される組み込みプロファイル

組み込みプロファイルに加えて、runtime/pprofパッケージを使用すると、カスタムプロファイルをエクスポートし、このプロファイルに寄与する実行スタックを記録するようにコードをインストルメント化できます。

Blobサーバーがあり、それ用のGoクライアントを作成していると想像してください。そして、ユーザーがクライアントで開かれたBlobをプロファイリングできるようにしたいとします。プロファイルを作成し、Blobのオープンとクローズのイベントを記録できるため、ユーザーは任意の時点で開いているBlobの数を知ることができます。

これは、いくつかのBlobを開くことができるblobstoreパッケージです。新しいカスタムプロファイルを作成し、Blobのオープンに寄与する実行スタックの記録を開始します。

package blobstore

import "runtime/pprof"

var openBlobProfile = pprof.NewProfile("blobstore.Open")

// Open opens a blob, all opened blobs need
// to be closed when no longer in use.
func Open(name string) (*Blob, error) {
    blob := &Blob{name: name}
    // TODO: Initialize the blob...

    openBlobProfile.Add(blob, 2) // add the current execution stack to the profile
    return blob, nil
}

そして、ユーザーがBlobを閉じたい場合は、現在のBlobに関連付けられた実行スタックをプロファイルから削除する必要があります。

// Close closes the blob and frees the
// underlying resources.
func (b *Blob) Close() error {
    // TODO: Free other resources.
    openBlobProfile.Remove(b)
    return nil
}

そして今、このパッケージを使用するプログラムから、blobstore.Openプロファイルデータを取得し、日常のpprofツールを使用して調べ、視覚化できるようになるはずです。

いくつかのBlobを開く小さなメインプログラムを書いてみましょう。

package main

import (
    "fmt"
    "math/rand"
    "net/http"
    _ "net/http/pprof" // as a side effect, registers the pprof endpoints.
    "time"

    "myproject.org/blobstore"
)

func main() {
    for i := 0; i < 1000; i++ {
        name := fmt.Sprintf("task-blob-%d", i)
        go func() {
            b, err := blobstore.Open(name)
            if err != nil {
                // TODO: Handle error.
            }
            defer b.Close()

            // TODO: Perform some work, write to the blob.
        }()
    }
    http.ListenAndServe("localhost:8888", nil)
}

サーバーを起動し、次にgo toolを使用してプロファイルデータを読み取り、視覚化します。

$ go tool pprof http://localhost:8888/debug/pprof/blobstore.Open
(pprof) top
Showing nodes accounting for 800, 100% of 800 total
      flat  flat%   sum%        cum   cum%
       800   100%   100%        800   100%  main.main.func1 /Users/jbd/src/hello/main.go

800個の開いているBlobがあり、すべてのオープンがmain.main.func1から来ていることがわかります。この小さな例では、それ以上何も見ることはありませんが、複雑なサーバーでは、開いているBlobで動作する最もホットなスポットを調べて、ボトルネックやリークを見つけることができます。


このコンテンツはGo Wikiの一部です。