[golang]调优工具pprof
CPU ProfilingGolang 提供了 pprof 包(runtime/pprof)用于输出运行时的 profiling 数据,这些数据可以被pprof工具(或者 go tool pprof,其为 pprof 的变种)使用。通常我们这样来使用 pprof 包: // 定义 flag cpuprofile
var cpuprofile = flag.String("cpuprofile","",0)">"write cpu profile to file")
func main() {
flag.Parse()
// 如果命令行设置了 cpuprofile
if *cpuprofile != "" {
// 根据命令行指定文件名创建 profile 文件
f,err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
}
// 开启 CPU profiling
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
...
假定我们编写的一个程序 mytest 中加入了上述代码则可以执行并生成 profile 文件: ./mytest -cpuprofile=mytest.prof
这里,我们生成了 mytest.prof profile 文件。有了 profile 文件就可以使用 go tool pprof 程序来解析此文件: go tool pprof mytest mytest. pprof 程序中最重要的命令就是 topN,此命令用于显示 profile 文件中的最靠前的 N 个样本(samples),例如(此例为http://blog.golang.org/profiling-go-programs中的例子):
上例中,第一列为运行到此行时的样本数,第二列为运行到此行或从此行调用的样本数,第三列为行号。如果需要显示汇编,可以使用命令 disasm(使用命令 weblist 可以同时显示源码和汇编代码,这里有一个范例)。通过样本数,我们可以定位到热点行,然后考虑适合的优化策略。 pprof 包pprof 包进行 profiling 有两种方式:
pprof 包预先定义了(还可以自己扩展)4 种快照模式:
相关 API 具体用法如下: // 根据名字查找 Profile
p := pprof.Lookup("heap")
// 将一个 pprof(程序)格式的快照写入 w
p.WriteTo(w,0)
这里的 WriteTo 方法原型为: func (p *Profile) WriteTo(w io.Writer,debug int) error
其中 debug 参数:
memory profiling以https://blog.golang.org/profiling-go-programs中的例子为例: // 定义 flag memprofile
var memprofile = flag.String("memprofile",0)">"write memory profile to this file")
...
// 需要 profiling 的函数
FindHavlakLoops(cfgraph,lsgraph)
if *memprofile != "" {
f,err := os.Create(*memprofile)
// WriteHeapProfile 等价于 Lookup("heap").WriteTo(w,0)
pprof.WriteHeapProfile(f)
// 关闭文件
f.Close()
return
}
使用 go tool pprof 程序打开生成的 profile 文件: top5
Total: 82.4 MB
56.3 68.4% 68.4% 56.4% .FindLoops
17.6 21.3% 89.7% 17main.(*CFG).CreateNode
8.0 9.7% 99.4% 25.6 31.NewBasicBlockEdge
0.5 0.6% 100.0% 0.6% itab
0.0 0.0% 100fmt.init
这里显示了函数当前大致分配的内存。类似 CPU profiling,通过 list 命令查看函数具体的内存分配情况: (pprof) list FindLoops
Total: 82.4 MB
ROUTINE ====================== main.FindLoops in /home/rsc/g/benchgraffiti/havlak/havlak3.go
56.3 56.3 Total MB (flat / cumulative)
...
1.9 1.9 268: nonBackPreds := make([]map[int]bool,size)
5.8 5.8 269: backPreds := make([][]270:
271: number := 272: header := 273: types := 274: last := 275: nodes := make([]*UnionFindNode,0)">276:
. . 277: for i := 0; i < size; i++ {
9.5 9.5 278: nodes[i] = new(UnionFindNode)
. . 279: }
...
. . 286: for i,bb := range cfgraph.Blocks {
. . 287: number[bb.Name] = unvisited
29.5 29.5 288: nonBackPreds[i] = make(bool)
. . 289: }
有了这些信息,我们就可以着手进行优化 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |