golang 内存监控

最近的一个golang项目上生产后,发现RES内存占用一直在轻微上涨:三天时间从一开始的40M,上涨到了60M左右。之前对golang的内存管理和垃圾回收机制一直不是很清晰,于是花些时间去把这个问题搞清楚。

1) VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义

我们需要关注的主要是RES内存

o: VIRT -- Virtual Image (kb)
      The  total  amount  of  virtual  memory  used  by the task.  It
      includes all code, data and shared libraries  plus  pages  that
      have  been  swapped out and pages that have been mapped but not
      used.
 p: SWAP  --  Swapped size (kb)
      Memory that is not resident but is present in a task.  This  is
      memory  that  has been swapped out but could include additional
      non-resident memory.  This column is calculated by  subtracting
      physical memory from virtual memory.
  q: RES  --  Resident size (kb)
      The non-swapped physical memory a task has used.
  r: CODE  --  Code size (kb)
      The  amount  of virtual memory devoted to executable code, also
      known as the 'text resident set' size or TRS.
  s: DATA  --  Data+Stack size (kb)
      The amount of virtual memory devoted to other  than  executable
      code, also known as the 'data resident set' size or DRS.
  t: SHR  --  Shared Mem size (kb)
      The amount of shared memory used by a task.  It simply reflects
      memory that could be potentially shared with other processes.

VIRT:virtual memory usage 虚拟内存
1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等等。
2、假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量

SHR:shared memory 共享内存
1、除了自身进程的共享内存,也包括其他进程的共享内存
2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小
3、计算某个进程所占的物理内存大小公式:RES – SHR
4、swap out后,它将会降下来

RES:resident memory usage 常驻内存
1、进程当前使用的内存大小,但不包括swap out
2、包含其他进程的共享
3、如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反
4、关于库占用内存的情况,它只统计加载的库文件所占内存大小

DATA
1、数据占用的内存。如果top没有显示,按f键可以显示出来。
2、真正的该程序要求的数据空间,是真正在运行中要使用的。

2) golang监控内存的方式

1 利用GCVIS进行可视化监控

原理可参考:http://holys.im/2016/07/01/monitor-golang-gc/
这是最简单的方式,好处是不用修改程序代码。

1)安装

go get https://github.com/davecheney/gcvis 或者git clone https://github.com/davecheney/gcvis 到本地自行安装

2)启动监控(要运行的文件是/path/to/binary)

有两种方式
1、 直接运行

./gcvis /path/to/binary

2、 管道重定向方式(standard error)

GODEBUG=gctrace=1  /path/to/binary  |& ./gcvis

我这里运行的是

env GOMAXPROCS=4 ./gcvis -o=false -p 12345  -i 10.107.101.1 /path/to/binary

可访问页面http://10.107.101.1:12345 获取可视化结果。

2 利用pprof进行监控

具体可参考:https://studygolang.com/articles/9940
go中有pprof包来做代码的性能监控主要涉及两个pkg:

#web服务器:
import (
    "net/http"
    _ "net/http/pprof"
)

#一般应用程序(实际应用无web交互)
import (
    "net/http"
    _ "runtime/pprof"
)

其实net/http/pprof中只是使用runtime/pprof包来进行封装了一下,并在http端口上暴露出来

1)修改代码

需要对原来的程序代码进行修改

web 服务器

如果你的go程序是用http包启动的web服务器,可以选择net/http/pprof。
只需要引入包_"net/http/pprof",然后就可以在浏览器中使用 http://localhost:port/debug/pprof/
直接看到当前web服务的状态,包括CPU占用情况和内存使用情况等。

服务进程

如果你的go程序不是web服务器,而是一个服务进程,也可以选择使用net/http/pprof包,同样引入包net/http/pprof,然后在开启另外一个goroutine来开启端口监听。

go func() {
        http.ListenAndServe("localhost:6060", nil)
}()

应用程序

如果你的go程序只是一个应用程序,比如计算fabonacci数列,那么你就不能使用net/http/pprof包了,你就需要使用到runtime/pprof。
具体做法就是用到pprof.StartCPUProfile和pprof.StopCPUProfile。
比如下面的例子:

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
func main() {
    flag.Parse()
    if *cpuprofile != "" {
        f, err := os.Create(*cpuprofile)
        if err != nil {
            log.Fatal(err)
        }
        pprof.StartCPUProfile(f)
        defer pprof.StopCPUProfile()
    }

运行程序的时候加一个--cpuprofile参数,比如 fabonacci --cpuprofile=fabonacci.prof
这样程序运行的时候的cpu信息就会记录到XXX.prof中了。

2)查看监控数据

两种方式:
1 WEB上直接查看,浏览器直接访问:http://XXX:6060/debug/pprof
2 通过 go tool pprof 查看
具体的数据字段含义参考
https://blog.csdn.net/m0_38132420/article/details/71699815
https://studygolang.com/articles/9940

3) FreeOSMemory()

折腾和很久,发现两种方式监控到的内存都比较稳定。但是TOP命令查看RES还是一直在增长。
查了很久的资料:
https://groups.google.com/forum/#!topic/Golang-Nuts/kuS4kLCwkbE
https://stackoverflow.com/questions/37382600/cannot-free-memory-once-occupied-by-bytes-buffer
https://golang.org/pkg/runtime/debug/#FreeOSMemory

最后发现,golang的内存即使被gc回收了,也不会立刻归还给OS的,除非你手动调用FreeOSMemory()
这也是RES内存一起比预期中高的原因

Some things to clear. Go is a garbage collected language, which means that memory allocated and used by variables is automatically freed by the garbage collector when those variables become unreachable (if you have another pointer to the variable, that still counts as "reachable").
Freed memory does not mean it is returned to the OS. Freed memory means the memory can be reclaimed, reused for another variable if there is a need. So from the operating system you won't see memory decreasing right away just because some variable became unreachable and the garbage collector detected this and freed memory used by it.
The Go runtime will however return memory to the OS if it is not used for some time (which is usually around 5 minutes). If the memory usage increases during this period (and optionally shrinks again), the memory will most likely not be returned to the OS

FreeOSMemory forces a garbage collection followed by an attempt to return as much memory to the operating system as possible. (Even if this is not called, the runtime gradually returns memory to the operating system in a background task.)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容