如何准确跟踪内存使用情况?

Posted

技术标签:

【中文标题】如何准确跟踪内存使用情况?【英文标题】:How to track memory usage accurately? 【发布时间】:2017-06-17 03:28:48 【问题描述】:

我正在尝试构建一个小工具,让我可以通过 Go 运行程序并跟踪内存使用情况。我正在使用 r.exec = exec.Command(r.Command, r.CommandArgs...) 运行命令,并使用 runtime.MemStats 跟踪内存使用情况(在单独的 go 例程中):

func monitorRuntime() 
    m := &runtime.MemStats
    f, err := os.Create(fmt.Sprintf("mmem_%s.csv", getFileTimeStamp()))
    if err != nil 
        panic(err)
    
    f.WriteString("Time;Allocated;Total Allocated; System Memory;Num Gc;Heap Allocated;Heap System;Heap Objects;Heap Released;\n")
    for 
        runtime.ReadMemStats(m)
        f.WriteString(fmt.Sprintf("%s;%d;%d;%d;%d;%d;%d;%d;%d;\n", getTimeStamp(), m.Alloc, m.TotalAlloc, m.Sys, m.NumGC, m.HeapAlloc, m.HeapSys, m.HeapObjects, m.HeapReleased))
        time.Sleep(5 * time.Second)
    

当我用一个简单的程序测试我的代码时(大约 12 小时),我注意到 Go 不断地分配更多的内存: System Memory Heap Allocation

我又做了一些测试,比如在没有任何其他代码的情况下运行monitorRuntime()函数,或者使用pprof,比如:

package main

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

func main() 
    http.ListenAndServe(":8080", nil)

但我仍然注意到内存分配一直在增加,就像在图表中一样。

如何准确跟踪我想通过 Go 运行的程序的内存使用情况? 我知道我过去使用的一种方法是使用/proc/$PID/statm,但该文件并不存在于每个操作系统(例如 MacOS 或 Windows)中

【问题讨论】:

请注意,for循环的每一步都将分配一些内存(主要是因为WriteString,iirc),并且该内存将持续到垃圾回收为止。在我自己的循环中看到了同样的事情,每次循环迭代分配大约一百个字节,直到垃圾收集。这不是泄漏,只是正常分配。 @VaD:ReadMemStats 尽可能准确,因为它显示了 Go 运行时所做的所有分配。也许跟踪gctrace 的输出以查看您的系统上的内存是如何收集的。 @Kaedys 在问这个问题之前我做了一些研究,我得出了同样的结论。即使它发生在更简单的程序中,例如将输出写入标准输出而不是文件,或者使用 pprof。但是我仍然无法弄清楚如何获得通过 Go 运行的命令的准确内存使用跟踪(使用 exec.Command),我希望能够判断该命令是否正在泄漏内存。 ***.com/a/44711589/2777965 【参考方案1】:

在 Linux (RedHat) 上,以下将显示内存使用情况: ps -No pid,comm,size,vsize,args:90

【讨论】:

以上是关于如何准确跟踪内存使用情况?的主要内容,如果未能解决你的问题,请参考以下文章

如何跟踪 Visual Studio 2017(C++)中的内存使用情况?

使用 PerformanceCounter 跟踪每个进程的内存和 CPU 使用情况?

如何获取运行 Node JS 应用程序的 k8s Pod 的当前和准确的内存使用情况

通过 Python 函数跟踪*最大*内存使用情况

在 PHP 中跟踪内存使用情况

如何在 iOS 中跟踪负责堆增长的代码