Go Wiki: CustomPprofProfiles
最初发布于 https://rakyll.org/custom-profiles/。
Go 开箱即用地提供了几个 pprof profile,用于从 Go 程序收集分析数据。
由 runtime/pprof 包提供的内置 profile
- profile:CPU profile 确定程序在积极消耗 CPU 周期时(而非睡眠或等待 I/O 时)将时间花在了哪里。
- heap:Heap profile 报告当前活动的分配;用于监控当前内存使用情况或检查内存泄漏。
- threadcreate:Thread creation profile 报告导致创建新 OS 线程的程序部分。
- goroutine:Goroutine profile 报告所有当前 goroutine 的堆栈跟踪。
- block:Block profile 显示 goroutine 在等待同步原语(包括定时器通道)时被阻塞的位置。Block profile 默认未启用;使用 runtime.SetBlockProfileRate 来启用它。
- mutex:Mutex profile 报告锁的争用。当您认为 CPU 未被充分利用是由于互斥锁争用时,请使用此 profile。Mutex profile 默认未启用,请参阅 runtime.SetMutexProfileFraction 来启用。
除了内置 profile,runtime/pprof 包还允许您导出自定义 profile,并对代码进行仪器化以记录对该 profile 有贡献的执行堆栈。
想象一下我们有一个 blob 服务器,我们正在为其编写一个 Go 客户端。我们的用户希望能够对客户端上的已打开 blob 进行分析。我们可以创建一个 profile 并记录打开和关闭 blob 的事件,这样用户就可以随时知道有多少 blob 已打开。
这是一个允许您打开一些 blob 的 blobstore 包。我们将创建一个新的自定义 profile 并开始记录导致 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 时,我们需要从 profile 中移除与当前 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
profile 数据,并使用我们日常的 pprof 工具来检查和可视化它们。
让我们编写一个打开一些 blob 的小型 main 程序。
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 读取和可视化 profile 数据。
$ go tool pprof https://: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 的一部分。