zl程序教程

您现在的位置是:首页 >  Java

当前栏目

pprof性能分析

2023-02-18 16:44:45 时间

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)