内存泄漏
通常,造成内存泄漏的原因有如下几个。
- 缓存。
- 队列消费不及时。
- 作用域未释放。
慎将内存当做缓存
缓存在应用中的作用举足轻重,可以十分有效地节省资源。因为它的访问效率要比I/O的效率高,一旦命中缓存,就可以节省一次I/O的时间。
但是在Node中,缓存并非物美价廉。一旦一个对象被当做缓存来使用,那就意味着它将会常驻在老生代中。缓存中存储的键越多,长期存活的对象也就越多,这将导致垃圾回收在进行扫描和整理时,对这些对象做无用功。
另一个问题在于,JavaScript开发者通常喜欢用对象的键值对来缓存东西,但这与严格意义上的缓存又有着区别,严格意义的缓存有着完善的过期策略,而普通对象的键值对并没有。
缓存限制策略
为了解决缓存中的对象永远无法释放的问题,需要加入一种策略来限制缓存的无限增长。
javascript
var LimitableMap = function (limit) {
this.limit = limit || 10;
this.map = {};
this.keys = [];
};
var hasOwnProperty = Object.prototype.hasOwnProperty;
LimitableMap.prototype.set = function (key, value) {
var map = this.map;
var keys = this.keys;
if (!hasOwnProperty.call(map, key)) {
if (keys.length === this.limit) {
var firstKey = keys.shift();
delete map[firstKey];
}
keys.push(key);
}
map[key] = value;
};
LimitableMap.prototype.get = function (key) {
return this.map[key];
};
module.exports = LimitableMap;
实现过程还是非常简单的。记录键在数组中,一旦超过数量,就以先进先出的方式进行淘汰。
缓存的解决方案
如何使用大量缓存,目前比较好的解决方案是采用进程外的缓存,进程自身不存储状态。外部的缓存软件有着良好的缓存过期淘汰策略以及自有的内存管理,不影响Node进程的性能。
在Node中主要可以解决以下两个问题
- 将缓存转移到外部,减少常驻内存的对象的数量,让垃圾回收更高效。
- 进程之间可以共享缓存。
- 使用Redis或Memcached
内存泄漏排查
可以借助第三方工具排除。