less /proc/$pid/smaps
通过上诉两个命令查找到比较可疑的内存地址
注意:dump内存会挂起应用进程,一定要确保没有流量流入再使用
使用gdb命令dump出内存
#先连接程序
gdb -pid $pid
#进入gdb调试模式dump内存
dump memory mem.bin 7f43dc000000 7f440e000000
#mem.bin是内存dump出来的文件,后面是地址
strings mem.bin > mem.log #将二进制文件读取成字符串并输出到文件,方便查阅
less mem.log
查看可能的代码位置,通过位置查看逻辑哪里有泄露。
我们项目没发现什么问题
3.通过对比pmap -x $pid | sort -k3 -n前后文件,发现内存量增加主要集中在RSS Dirty这两项位置。
vm.dirty_background_ratio 是内存可以填充脏数据的百分比。这些脏数据稍后会写入磁盘,pdflush/flush/kdmflush这些后台进程会稍后清理脏数据。比如,我有32G内存,那么有3.2G的脏数据可以待着内存里,超过3.2G的话就会有后台进程来清理。
vm.dirty_ratio是可以用脏数据填充的绝对最大系统内存量,当系统到达此点时,必须将所有脏数据提交到磁盘,同时所有新的I/O块都会被阻塞,直到脏数据被写入磁盘。这通常是长I/O卡顿的原因,但这也是保证内存中不会存在过量脏数据的保护机制。
vm.dirty_background_bytes和vm.dirty_bytes是另一种指定这些参数的方法。如果设置_bytes版本,则_ratio版本将变为0,反之亦然。
vm.dirty_expire_centisecs 指定脏数据能存活的时间。在这里它的值是30秒。当 pdflush/flush/kdmflush 在运行的时候,他们会检查是否有数据超过这个时限,如果有则会把它异步地写到磁盘中。毕竟数据在内存里待太久也会有丢失风险。
vm.dirty_writeback_centisecs 指定多长时间 pdflush/flush/kdmflush 这些进程会唤醒一次,然后检查是否有缓存需要清理。
通过这里分析内存增加在rss和dirty,就应该和程序没多大关系,应该是某些io操作导致的,在本机写入磁盘的只有日志文件,所以考虑是日志输出量大导致的,将日志全部注释掉测试,内存没有增加,问题定位到了,下面就是怎么解决日志输出量大的问题了。
堆外内存排查参考
rss和dirty参考