【Golang】火焰图空白部分是什么?

起因

被同事灵魂拷问:图中这块空白是什么东西?

豆包回答说是数据采样不完整,特定函数或代码段未被调用之类的原因,感觉都不太合理。

之前看过一篇文章说:Heap Profiling的采样是无时无刻不在发生的,执行一次profiling仅仅是dump一下迄今为止的数据快照。这篇文章更加推翻了前面"数据采样不完整"的假设。那火焰图中的空白到底是啥,我们亲自试一下。

实验

参考:使用火焰图对 Go 程序进行性能分析

实验设计

在一个函数中调用另外的函数,在多种位置申请内存,查看火焰图的空白情况。

前置准备

  1. 安装环境
  2. 编写测试代码
  3. 在Goland中运行测试代码,可以通过 pprof 的 HTTP 接口访问http://localhost:8000/debug/pprof/heap?debug=1
  4. 在终端中执行以下命令,在页面中展示火焰图。其中,-http=":8081"表示用于查看火焰图的端口,http://localhost:8000/debug/pprof/heap表示采集的数据源。需要注意,每次运行此命令时,生成的是当前堆快照,如果代码有变更,或者想要获取最新结果,需要中断后重新运行此命令。
    go tool pprof -http=":8081" http://localhost:8000/debug/pprof/heap
  5. 火焰图分析方法:选择VIEW - Flame Graph (old)后,再选择SAMPLE - alloc_space。我们主要看这个,其它的选项也可以参考。

函数调用关系

复制代码
func allocate1() {
     allocate2()
     allocate3()
}

代码1:allocate1本身占用空间

go 复制代码
package main

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

func allocate1() {
    var s []string
    for i := 0; i < 10000; i++ {
       // allocate1占用的空间
       for i := 0; i < 10; i++ {
          s = append(s, "This is a sample string")
       }
       // allocate2占用的空间
       allocate2()
       // allocate3占用的空间
       allocate3()
    }
}

func allocate2() {
    var s []string
    for i := 0; i < 10; i++ {
       s = append(s, "This is a sample string")
    }
}
func allocate3() {
    var s []string
    for i := 0; i < 10; i++ {
       s = append(s, "This is a sample string")
    }
}

func main() {
    go func() {
       for {
          allocate1()
          time.Sleep(1 * time.Second)
       }
    }()
    http.ListenAndServe(":8000", nil)
}

生成的火焰图:

代码2:allocate本身不占空间

把13-15行注释掉,让allocate1不占空间

go 复制代码
package main

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

func allocate1() {
    //var s []string
    for i := 0; i < 10000; i++ {
       // allocate1占用的空间
       //for i := 0; i < 10; i++ {
       // s = append(s, "This is a sample string")
       //}
       // allocate2占用的空间
       allocate2()
       // allocate3占用的空间
       allocate3()
    }
}

func allocate2() {
    var s []string
    for i := 0; i < 10; i++ {
       s = append(s, "This is a sample string")
    }
}
func allocate3() {
    var s []string
    for i := 0; i < 10; i++ {
       s = append(s, "This is a sample string")
    }
}

func main() {
    go func() {
       for {
          allocate1()
          time.Sleep(1 * time.Second)
       }
    }()
    http.ListenAndServe(":8000", nil)
}

生成的火焰图:

结论

当allocate1本身占用空间的时候,火焰图中的空白存在。当allocate1本身不占用空间的时候,火焰图被填满,不存在空白。说明空白的部分是上一级函数内部对象占用的空间。

相关推荐
Algebraaaaa1 小时前
为什么C++主函数 main 要写成 int 返回值 | main(int argc, char* argv[]) 这种写法是什么意思?
开发语言·c++
java1234_小锋2 小时前
一周学会Matplotlib3 Python 数据可视化-绘制饼状图(Pie)
开发语言·python·信息可视化
悟能不能悟3 小时前
能刷java题的网站
java·开发语言
IT古董3 小时前
【第四章:大模型(LLM)】05.LLM实战: 实现GPT2-(6)贪婪编码,temperature及tok原理及实现
android·开发语言·kotlin
程序员陆通3 小时前
Java高并发场景下的缓存穿透问题定位与解决方案
java·开发语言·缓存
澡点睡觉4 小时前
golang的继承
开发语言·后端·golang
洛阳泰山6 小时前
基于 Easy Rules 的电商订单智能决策系统:构建可扩展的业务规则引擎实践
java·开发语言·规则引擎·easy rules
kushu76 小时前
Java 包
java·开发语言
xiaobobo33307 小时前
C语言中关于普通变量和指针变量、结构体包含子结构体或包含结构体指针的一些思考
c语言·开发语言·结构体指针
java1234_小锋7 小时前
周学会Matplotlib3 Python 数据可视化-绘制折线图(Lines)
开发语言·python·信息可视化·matplotlib·折线图·matplotlib3