这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
pprof性能调优 | 青训营笔记
性能调优原则
- 要依靠数据不是猜测
- 要定位最大瓶颈而不是细枝末节
- 不要过早优化()
- 不要过度优化(版本更新迭代的不兼容问题)
pprof-功能简介
- 一个查询耗费CPU、Memory多少的性能分析工具
- 可视化、分析性能
- 采样部分-通过采样程序运行时的CPU、堆内存、goroutine、锁竞争.阻塞调用和系统线程的使用数据展示-用户可以通过列表、调用图、火焰图、源码、反汇编等视图去展示采集到的性能指标
pprof界面
运行main.go主程序(注释是对代码的分析)
func main() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
log.SetOutput(os.Stdout)
runtime.GOMAXPROCS(1) //限制CPU使用数
runtime.SetMutexProfileFraction(1) //开启锁调用跟踪
runtime.SetBlockProfileRate(1) //开启阻塞调用跟踪
go func() {
//启动http server 端口号为 6060
if err := http.ListenAndServe(":6060", nil); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
for {
for _, v := range animal.AllAnimals {
v.Live()
}
time.Sleep(time.Second)
}
}
程序运行之后输入 http://localhost:6060/debug/pprof/可以查看pprof监控界面 (我们可以通过这个大概了解程序运行情况并进行性能分析)
各个指标的信息
- allocs:内存分配情况
- blocks:阻塞操作情况
- cmdline:程序启动命令
- goroutine:当前所有goroutine的堆栈信息
- heap:堆上内存使用情况(同alloc)
- mutex:锁竞争操作情况
- profile: CPU占用情况
- threadcreate:当前所有创建的系统线程的堆栈信息
- trace:程序运行跟踪信息 (比较复杂 需要另外的工具解析,暂不涉及)
优化CPU占用
我们先来看一下程序的CPU占用
通过PID可以看得出来占用量还是很高的
在TerMinal窗口输入:
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
,先pprof工具采集10秒的数据到profile文件中
- pro的采样结果是将一段时间内的信息汇总输出到文件中,所以首先需要拿到这个prfie文件。你可以直接使用暴露的接口链接下载文件后使用,也可以直接用ppof工具连接这个接口下载需要的数据。这里我们使用go tool pprof +采样链接来启动采样。
- 链接中就是刚才扎弹]程序展露出来的接口,如果直接用浏览器打开这个链接,会启动60秒的采样,并在结束的时候下载文件
在窗口中输入top指令,
查看占用CPU资源较多的调用
- Flat:当前函数的占用
- Flat%:Flat占总量的比例
- Sum%:上面所有行的Flat%总和
- Cum (Cumulative) :当前函数加上其调用函数的总占用
- Cum%: Cum占总量的比例
我们将占最大的调用代码所在的位置点开后可以看见这样一串代码 (list Eat 可以看到其代码内容)
func (t *Tiger) Eat() {
/*log.Println(t.Name(), "eat")
loop := 10000000000
for i := 0; i < loop; i++ {
// do nothing
}*/
}
我们将其注释掉 重新启动服务后会发现 cpu资源调度一下子就变少了
同理,我们将其他的性能炸弹一个个的找出来,注释掉,问题就清空啦
以下是本次实验所埋设的炸弹
-
协程问题
-
内存占用
-
mutex 锁的引用
-
block 阻塞问题