pprof性能分析

pprof工具原理来自于在Scala Days 2011上Robert Hundt发表的一篇名为 Loop Recognition in C++/Java/Go/Scala.的论文。这篇论文实现了一种特定的循环查找算法,例如您可以在C ++,Go,Java,Scala中使用编译器的流分析传递,然后使用这些程序得出这些语言中典型性能问题的结论。该论文中提出的Go程序运行速度非常慢,这使它成为演示如何使用Go的分析工具来实现慢速程序并使其更快的绝佳机会。

web程序


在main.go中加入如下代码:

import (
    "log"
    "net/http"
    _ "net/http/pprof"
)

func main() {
    go func() {
        log.Println(http.ListenAndServe(":8061", nil))
    }()

    // ... Other codes
}

_ "net/http/pprof" 这行代码很重要,需要手动加上,否则也无法在浏览器查看。启动成功后,可在浏览器输入网址:http://localhost:8061/debug/pprof

http://localhost:8061/debug/pprof

关键名词解释(Profile)
  • profile(cpu profiling),默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件
  • block,查看导致阻塞同步的堆栈跟踪
  • goroutine, 查看当前所有运行的 goroutines 堆栈跟踪
  • heap(Memory Profiling),查看活动对象的内存分配情况
  • mutex(Mutex Profiling),查看导致互斥锁的竞争持有者的堆栈跟踪
  • threadcreate,查看创建新OS线程的堆栈跟踪

分析

火焰图

go tool pprof --http=":8081" [binary] [profile]
如:go tool pprof --http=":8081" bdms mem-32057.memprof

flame graph

cpu

centos命令行窗口输入:go tool pprof http://localhost:8061/debug/pprof/profile,30s后进入交互式界面:

go tool pprof http://localhost:8061/debug/pprof/profile

你也可以指定cpu的监测时间,加入seconds参数: go tool pprof http://localhost:8061/debug/pprof/profile?seconds=60

go tool pprof http://localhost:8061/debug/pprof/profile?seconds=60

top

输入top查看占用cpu前10的函数,也可指定top数,如top25


top

启用CPU分析时,Go程序每秒停止大约100次,并在当前正在执行的goroutine堆栈上记录由程序计数器组成的样本。

  • flat:给定函数上运行耗时
  • flat%:占整个 CPU 运行耗时总比例
  • sum%:给定函数累积使用 CPU 总比例
  • cum:当前函数加上它之上的调用运行总耗时
  • cum%:占整个 CPU 运行耗时总比例
  • 最后一列是函数名

要按第四和第五列排序,请使用-cum(for cumulative)标志:


top -cum
web

堆栈跟踪示例包含有关函数调用关系的有趣数据,而不是文本列表可以显示的数据。该web命令以SVG格式写入配置文件数据的图形,并在Web浏览器中打开它。(还有一个gv命令可以编写PostScript并在Ghostview中打开它。对于任一命令,您需要安装graphviz)。或者sudo yum install graphviz on CentOS。

(pprof) web
web

我们可以看到该程序将大部分时间都花在某个函数操作上,这时可以告诉web只使用包含特定功能的样本,例如bccsp来清除一些噪音。

(pprof) web bccsp
web bccsp

现在我们已经大致了解了大局,现在是时候放大一个特定的功能了。让我们先看一下(*SharedDataController).Upload,因为它是一个较短的功能:

(pprof) list Upload
list Upload

列表显示了该Upload函数的源代码(实际上,是对于与正则表达式匹配Upload的每个函数)。第一行是采集的总体花费时间,前三列是运行该行或从该行调用的代码中采集的时间,以及文件中的行号。

alloc (memory)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 性能优化是个永恒的话题,而很多时候我们在作性能优化的时候,往往基于代码上面的直觉,把所有能想到的优化都优化了一遍,...
    hatlonely阅读 1,696评论 0 5
  • 原文地址:Golang 大杀器之性能剖析 PProf 前言 写了几吨代码,实现了几百个接口。功能测试也通过了,终于...
    EDDYCJY阅读 73,133评论 7 78
  • 《Go语言四十二章经》第二十六章 测试 作者:李骁 在Go语言中,所有的包都应该有必要文档和注释,当然同样甚至更为...
    ffhelicopter阅读 1,241评论 0 3
  • runtime 包 提供了运行时与系统的交互,比如控制协程函数,触发垃圾立即回收等等底层操作,下面我们就运行时能做...
    酷走天涯阅读 4,927评论 2 7
  • 无虐不运动,你会挖坑没关系,我会填啊 23:00-5:21 感谢自己的固执让自己昨天变成超人,完成了一直不敢开始的...
    yyang999阅读 198评论 1 4