Vit*_*aev 14

我总是对Go应用程序不断增长的住宅内存感到困惑,最后我不得不学习Go生态系统中存在的分析工具.运行时在runtime.Memstats结构中提供了许多指标,但可能很难理解它们中的哪一个可以帮助找出内存增长的原因,因此需要一些额外的工具.

分析环境

main
import(
    metrics "github.com/tevjef/go-runtime-metrics"
)
func main() {
    //...
    metrics.DefaultConfig.CollectionInterval = time.Second
    if err := metrics.RunCollector(metrics.DefaultConfig); err != nil {
        // handle error
    }
}
InfluxDBGrafanaDocker
docker run --name influxdb -d -p 8086:8086 influxdb
docker run -d -p 9090:3000/tcp --link influxdb --name=grafana grafana/grafana:4.1.0
GrafanaInfluxDBGrafana

在此输入图像描述

从https://grafana.com导入仪表板#3242(Grafana主页 - >左上角 - >仪表板 - >导入):

在此输入图像描述

Influxdb

内存消耗分析

SysRSSHeapSysHeapIdleSysHeapReleased
HeapIdle minus HeapReleased estimates the amount of memory    
that could be returned to the OS, but is being retained by
the runtime so it can grow the heap without requesting more
memory from the OS.

在此输入图像描述在此输入图像描述

对于那些试图调查内存消耗问题的人,我建议按照所描述的步骤排除一些微不足道的错误(比如goroutine leak).

明确释放内存

debug.FreeOSMemory()
// in the top-level package
func init() {
   go func() {
       t := time.Tick(time.Second)
       for {
           <-t
           debug.FreeOSMemory()
       }
   }()
}

对照

实际上,与默认条件相比,这种方法节省了大约35%的内存.