原创分享 Go 高性能系列教程:读懂 pprof 生成的报告

yudotyang · 2021年05月29日 · 794 次阅读
本帖已被设为精华帖!

pprof 的目标是生成可视化的检测报告。报告是根据采集的样本数据从一个跟节点位置开始按调用关系生成层次化的结构。每个位置包含两个值:

  • flat:当前位置自身消耗的值(不包含函数内的调用消耗)
  • cum:当前位置及子位置累计的消耗值(即当前函数以及所有调用的函数总消耗)

pprof 生成报告的形式有两种:文字形式和可视化图形

文字形式报告

pprof 的文字报告用文字的格式展示了位置的层次结构

  • -text:打印每个位置条目,每行一个,包括单位值和累计值
  • -tree:按树状打印每个位置条目,包括该职位的父节点和子节点
  • -peek=regex:打印位置条目及其所有前置项和后续项,而不修剪任何条目
  • -traces:打印每一行的样本

文字报告中有 5 个指标:Flat、Flat%、Sum%、Cum、Cum%

  • Flat:函数自身运行耗时
  • Flat%:函数自身耗时比例
  • Sum%:指的就是每一行的flat%与上面所有行的flat%总和
  • Cum:当前函数加上它所有调用栈的运行总耗时
  • Cum%:当前函数加上它所有调用栈的运行总耗时比例

举例说明:函数demo由三部分组成:调用函数foo、自己直接处理一些事情、调用函数bar,其中调用函数foo耗时 1 秒,自己直接处理事情耗时 3 秒,调用函数bar耗时 2 秒,那么函数demoflat耗时就是 3 秒,cum耗时就是 6 秒。

func demo() {
    foo() // takes 1s
    do something directly // takes 3s
    bar() // takes 2s
}

如下图示例:

Sum% 值是当前行及上面行的累加和占比。如图所示中,第一行的 Flat% 是 98.41%,则第一行的 Sum% 是 98.41%。第二行的 Flat% 是 1.59%,则第二行的 Sum% 则是 1.59%+98.41%=100%。

可视化图形

在图形化的包中包含节点节点之间的边字体三个元素。而每个元素又具有颜色大小两个属性。下面我们一一解析各个元素和属性所代表的含义。

节点颜色:

  • 红色代表 cum 值为正,且越大
  • 绿色代表 cum 值为负,且越小。
  • 灰色代表 cum 值接近 0

节点字体大小:

  • 字体越大代表较大的绝对单位值
  • 字体越小代表较小的绝对单位值

边线及权重

  • 较粗的边线代表该路径下使用了更多的资源
  • 较细的边线代表该路径下使用了较少的资源

边线颜色

  • 红色代表值为正,且越大
  • 绿色代表值为负,且越小
  • 灰色代表值接近 0

边线样式

  • 虚线边:两个连接位置之间的某些节点已被删除,未显示全。为限制图形整体的大小,pprof 会自动裁剪一部分节点,而非都显示
  • 实线边:一个位置直接调用另一个位置
  • 内联边标记:被调用函数已经被内联到调用函数中

我们以下面的图形为例::

  • 节点

    • (*Rand).Read 节点的字体是小字体,颜色为灰色,代表自身值和累计值都比较小,接近于 0
    • (*compressor).deflate 节点的字体较大,节点为红色,代表自身值和累计值都较大。
    • (*Writer).Flush 节点的字体较小,节点为红色,代表是自身值较小,但累计值较大。
    • 在(*Writer).Write 和 (*compressor).write 之间的边:
      • 因为是虚线,在这两个节点之间有些节点被删除了
      • 因为是红色粗线,说明在这两个节点之间的调用栈上耗费了更多的资源
    • 在 (*Rand).Read 和 read 之间的边:
      • 因为是虚线,所以在这两个节点之间有些节点被删除了
      • 因为是灰色细线,说明在这两个节点之间的调用栈上耗费了较少的资源,接近于 0
    • 在 read 和 (*rngSource).Int63 之间的边:
      • 因为是实线,在这两个节点之间没有其他节点,是直接调用。
      • 因为是灰色细线,说明在这两个节点之间的调用栈上耗费了较少的资源,接近于 0

总结

在图形化中,颜色越深(红色)、字体越大代表消耗的资源越多(如果是 cpu 性能则耗时更长、如果是内存则占用更高)。在边线路径中,边线颜色越深、越粗,代表该路径下消耗的资源越多,反之代表消耗的资源越少。

在图形化中,pprof 为了图形化的整体大小,会自动删减一些节点,所以,图形界面中显示的并不是所有的节点。这里通过边线是实线还是虚线来体现。虚线代表两个节点之间有其他的节点调用,但未显示。实线则代表两个节点之间是直接调用的。

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
astaxie 将本帖设为了精华贴 05月29日 03:58
cloudy GoCN 每日新闻 (2021-05-29) 中提及了此贴 05月29日 07:24
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册