测试pprof
查看cpu
占用
首先,我们声明一个耗时函数。传递一个time.Duration
的数据类型,表示函数执行的时间。注意,这里不能使用time.Sleep
,它得不到cpu
的执行。函数如下:
// 耗时函数
func consumer(ctx context.Context, s time.Duration) {
subCtx, _ := context.WithTimeout(ctx, s)
i := 0
for {
select {
case <-subCtx.Done():
fmt.Println(i)
return
default:
i = i + 2
}
}
}
我们再声明一个冗余的函数,这个函数调用consumer
,同时Copy
一份consumer
的逻辑
// 间接耗时4s
func indirectConsumer(ctx context.Context, s time.Duration) {
consumer(ctx, s)
// copy同一份代码
subCtx, _ := context.WithTimeout(ctx, s)
i := 0
for {
select {
case <-subCtx.Done():
fmt.Println(i)
return
default:
i = i + 2
}
}
}
最后,我们写一个Test
,来生成cpu_profile
文件。
// 生成CPU Profile文件
func TestConsumer(t *testing.T) {
pf, err := os.OpenFile("cpu_profile", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}
defer pf.Close()
pprof.StartCPUProfile(pf)
defer pprof.StopCPUProfile()
ctx := context.Background()
// 耗时2s
consumer(ctx, time.Second*2)
// 耗时4s
indirectConsumer(ctx, time.Second*2)
}
查看我们生成的pprof
文件,这里我们使用web
的方式来查看。在命令行执行:
go tool pprof -http=:1888 cpu_profile
页面直接跳转到浏览器,并提供了很多菜单选项。我们看一下我机器上Top
的情况:
关注一下local/one-case.indirectConsumer
和local/one-case.consumer
,他们的占比基本是相同的,这也跟我们的预期是相同的。
通过查看Graph
我们可以清楚的看到调用的流程。Test
内部直接调用了consumer
函数,而indirectConsumer
也调用了consumer
函数。
通过Source
我们可以看到具体的代码的耗时占比。它明确的表示了flat
和cum
占用的时长。从某种意义上来说,这才是所谓的cpu
的直接调用和间接调用关系。我们使用indirectConsumer
为例:
如果觉得Graph
图拉的很长,我们可以选择Flame Graph
来查看。我们也展示一下:
有疑问加站长微信联系(非本文作者)