记录这个主要是为了写公司项目用的
前言
这里主要介绍pprof runtime/pprof主要是工具型程序的分析
- CPU profiling(CPU 性能分析):这是最常使用的一种类型。用于分析函数或方法的执行耗时;
- Memory profiling:这种类型也常使用。用于分析程序的内存占用情况;
- Block profiling:这是 Go 独有的,用于记录 goroutine 在等待共享资源花费的时间;
- Mutex profiling:与 Block profiling 类似,但是只记录因为锁竞争导致的等待或延迟。
使用
pprof 使用非常简单。首先调用pprof.StartCPUProfile()启用 CPU profiling。它接受一个io.Writer类型的参数,pprof会将分析结果写入这个io.Writer中。为了方便事后分析,我们写到一个文件中。
在要分析的代码后调用pprof.StopCPUProfile()。那么StartCPUProfile()和StopCPUProfile()之间的代码执行情况都会被分析。方便起见可以直接在StartCPUProfile()后,用defer调用StopCPUProfile(),即分析这之后的所有代
使用的库
- runtime/pprof:采集工具型应用运行数据分析
- net/http/pprof:采集服务型应用运行时数据进行分析
代码+演示
代码是方便理解的,实际演示中不存在 ```go // runtime_pprof/main.go package main
import ( “flag” “fmt” “os” “runtime/pprof” “time” )
// 一段有问题的代码 func logicCode() { var c chan int for { select { case v := <-c: fmt.Printf(“recv from chan, value:%v\n”, v) default:
}
}
}
func main() { var isCPUPprof bool var isMemPprof bool
flag.BoolVar(&isCPUPprof, "cpu", false, "turn cpu pprof on")
flag.BoolVar(&isMemPprof, "mem", false, "turn mem pprof on")
flag.Parse()
if isCPUPprof {
file, err := os.Create("./cpu.pprof")
if err != nil {
fmt.Printf("create cpu pprof failed, err:%v\n", err)
return
}
pprof.StartCPUProfile(file)
defer pprof.StopCPUProfile()
}
for i := 0; i < 8; i++ {
go logicCode()
}
time.Sleep(20 * time.Second)
if isMemPprof {
file, err := os.Create("./mem.pprof")
if err != nil {
fmt.Printf("create mem pprof failed, err:%v\n", err)
return
}
pprof.WriteHeapProfile(file)
file.Close()
}
}
```
go tool pprof cpu.pprof
我们可以在交互界面输入top3来查看程序中占用CPU前3位的函数
- flat:当前函数占用CPU的耗时
- flat::当前函数占用CPU的耗时百分比
- sun%:函数占用CPU的耗时累计百分比
- cum:当前函数加上调用当前函数的函数占用CPU的总耗时
- cum%:当前函数加上调用当前函数的函数占用CPU的总耗时百分比
- 最后一列:函数名称
我们还可以使用list 函数名命令查看具体的函数分析
下载graphviz 将graphviz安装目录下的bin文件夹添加到Path环境变量中。 在终端输入dot -version查看是否安装成功
go还提供了可视化的工具。我们只要输入web这个命令,就能得到一张svg图,可通过浏览器打开
不安装graphviz会报以下错误
从这里我们可以得知到底那个函数的那个地方出现了性能损耗,尝试对其优化