内存泄漏定义
内存泄漏,意昧着存着内存既不被使用,又不被回收。处理内存泄漏,则是找那些不被使用又不会被释放的变量,处理了这些变量,问题一般就可以解决了。一般出现在闭包,定时器,大循环和递增的全局变量上。在浏览器中,内存泄漏问题并不是致命问题,因为很多时候,在网页过于卡顿,用户一般刷新浏览器则可。而使用nodejs实现服务器,对于内存泄漏,则需要比较重视啦。
nodejs内存管理机制
nodejs是由Google公司开发的V8引擎管理内存。
一个运行的程序通常是通过在内存中分配一部分空间来表示的。这部分空间被称为驻留集(Resident Set)。 V8的内存管理模式有点类似于[Java虚拟机(JVM)]。事实上,JVM和V8引擎,虚拟机专家Lars Bak都是其主力开发。
V8引擎会将内存进行分段:
代码 Code:实际被执行的代码
栈 Stack:包括所有的携带指针引用堆上对象的值类型(原始类型,例如整型和布尔),以及定义程序控制流的指针。
堆 Heap:用于保存引用类型(包括对象、字符串和闭包)的内存段
在Node.js中,当前的内存使用情况可以轻松的使用process.memoryUsage()
进行查询
process.memoryUsage()函数返回的对象包含:
{ rss: 4935680, heapTotal: 1826816, heapUsed: 650472 }
常驻集的大小 - rss
堆的总值 - heapTotal
实际使用的堆 - heapUsed
一般来讲,如果heapUsed 和 heapTotal 长时间运行一直递增,意昧着内存泄漏。
如果检测内存泄漏
memwatch-next
memwatch 目前已经没人管理,npm已经没法安装。但出现了一个与memwatch相近的检测内存泄漏工具。
memwatch.on('leak', function(info) { ... });
leak事件用于判断在5次Gc内存回收中,heapUsed是否一致上升。若是,则出现leak事件。
- memwatch-next。
https://github.com/marcominetti/node-memwatch#readme
node-heapdump
node-heapdump用于捕捉对快照。
- node-heapdump
https://github.com/bnoordhuis/node-heapdump
devTool
这个是今年初出的 Node.js 调试工具,基于 Electron 将 Node.js 和 Chromium 的功能融合在了一起。操作起来比 node-inspector 方便,开放的 Timeline 功能还是比较实用的,虽然不是实时显示。
仅需要 devtool xxx.js,还可以通过 .devtoolrc 来进行参数定制
Easy-Monitor
Easy-Monitor是一个轻量级的Node项目性能监控工具,能在线上生产环境运行,主要帮助开发者找出执行时间最久或者超出预期的一系列函数,以及运行过程中v8引擎无法优化的一系列函数。
https://github.com/hyj1991/easy-monitor
笔者个人体会
其实还有其他一些内存泄漏检测判断的工具,比如阿里提供的alinode,这里就不做介绍。nodejs内存其实是一个很大的问题,如果检测出自身代码存在问题,那么修改代码则可。但有时候不是你自身代码出现问题,而是引用的第三方包出现内存泄漏,这个
比较麻烦。有时候甚至会出现node内核出现问题,或V8堆内存无问题,但Rss还在不停上涨,这个时候就要考虑使用C++外部件或buffer出现泄漏。
对于某些不太严重的泄漏,为避免消耗太多尽力。也可以采用定时重启或超过最大内存重启方式。归根到底,处理nodejs内存泄漏是一件很依赖经验的工作。多做多练才是王道。
参考
http://taobaofed.org/blog/2016/04/15/how-to-find-memory-leak/
http://taobaofed.org/blog/2016/01/14/nodejs-memory-leak-analyze/