深入理解Golang内存性能剖析(memprofile)输出行为
深入理解Golang内存性能剖析(memprofile)输出行为 我不确定如何解读以下内存性能分析输出。我想我对其根本原理存在误解。
显示的输出是在查看性能分析时使用了“-base”选项得到的(inuse_space)。 //注意:在获取内存性能分析之前,会强制运行垃圾回收器。
场景
- 启动服务
- 获取初始内存性能分析
- 加入一个设备(创建一个goroutine)
- 配置设备
- 离开设备(退出goroutine)
- 获取操作后的内存性能分析
经过调查,我发现处理设备的goroutine累计分配了15KB的内存。
由于goroutine已经退出,这意味着在堆上分配的数据(在这个例程中)一定还在某个地方被引用着。否则,垃圾回收器应该已经将其清理掉了。(希望确认这种思路是否正确)。
现在,查看goroutine调用的最底层代码,我发现json.Marshal函数累计分配了14.62KB。

. 14.62kB kvPairExportJsonResult, err := json.Marshal(kvPairExportResult)
这意味着,在调用例程结束后,json.Marshal()函数在堆上存储的某些信息仍然被引用着。(也希望确认这一点。)
- 我假设
json.Marshal()的底层代码不会保留对其解析数据的引用。 - 因此,我不得不假设
kvPairExportJsonResult被我的代码的某个部分引用了。
查看代码,我并没有立即发现有什么会创建对kvPairExportJsonResult的引用。之后我决定进行一些测试。
//添加test1变量,进行相同的调用
//由于test1从未被使用,只是被打印。我预期test1在goroutine结束后不会保留在堆上。
kvPairExportJsonResult, err := json.Marshal(kvPairExportResult)
test1, err1 := json.Marshal(kvPairExportResult)
fmt.Println(test1, err1)
//查看内存性能分析输出,测试结果确实符合我的预期。
. 14.62kB kvPairExportJsonResult, err := json.Marshal(kvPairExportResult)
. . test1, err1 := json.Marshal(kvPairExportResult)
当我调换顺序时,真正的困惑开始了。
//预期test1不会被分配到堆上,因为它之后没有被引用(只打印了一次)并且goroutine退出了。
test1, err1 := json.Marshal(kvPairExportResult)
fmt.Println(test1, err1)
kvPairExportJsonResult, err := json.Marshal(kvPairExportResult)
//查看内存性能分析输出,很明显我没有看到预期的结果。
. 14.62kB test1, err1 := json.Marshal(kvPairExportResult)
. . fmt.Println(test1, err1)
. . kvPairExportJsonResult, err := json.Marshal(kvPairExportResult)
嗯?奇怪……可能是因为编译器优化。 所以我关闭了优化,并再次用额外的变量进行了测试。
//现在内存肯定应该在第二次调用时分配....(?!?)
var test []KVPairExport
test1, err1 := json.Marshal(test)
fmt.Println(test1, err1)
kvPairExportJsonResult, err := json.Marshal(kvPairExportResult)
. 14.62kB var test []KVPairExport
. . test1, err1 := json.Marshal(test)
. . fmt.Println(test1, err1)
. . kvPairExportJsonResult, err := json.Marshal(kvPairExportResult)
我不理解最后两个例子中显示的行为。 这甚至推翻了我的两个假设,并让我质疑我对这些机制的理解。
一个在打印后从未使用过的变量,怎么还会在某个地方被引用呢? 一个变量怎么会有“累计”分配却没有平坦分配?更奇怪的是,为什么它仍然保持着和之前完全相同的数量(14.62KB)? 为什么最后一个例子中的最后一行没有显示分配,而第一个(和第二个)例子却显示了?
我对这些结果感到有些困惑,我不确定是否可以信任它们。 我非常乐意接受任何帮助。
更多关于深入理解Golang内存性能剖析(memprofile)输出行为的实战教程也可以访问 https://www.itying.com/category-94-b0.html


