内存控制
V8 的垃圾回收机制与内存限制
V8 的内存限制
- 只能使用部分内存,导致 Node 无法直接操作大内存对象
- 在 V8 中,所有的 JS 对象都是通过堆来进行分配的
- 限制堆大小原因是 V8 的垃圾回收机制,垃圾回收中引起 JS 线程暂停执行的时间,应用的性能和响应能力会直线下降
- V8 的垃圾回收机制
高效使用内存
作用域
- 全局变量需要进程退出才能释放,可以通过 delete 来删除引用关系,或重新赋值让旧的对象脱离引用关系
- 在 V8 中通过 delete 删除对象的数学有可能导致干扰 V8 的优化,所以通过赋值解除引用更好
闭包
- 一旦有变量引用中间函数,这个中间函数将不会被释放,同时也会使原始的作用域不会得到释放,作用域中产生的内存占用也不会得到释放
内存指标
查看内存使用情况
- 查看进程内存占用
process.memoryUsage()
- 查看系统内存占用
os.totalmem() os.freemem()
- 查看进程内存占用
堆外内存
- 堆外内存可以突破内存限制的问题
Node 的内存构成主要由通过 V8 进行分配的部分和 Node 自行分配的部分
- 受 V8 的垃圾回收限制的主要是 V8 的堆内存
内存泄露
造成内存泄露的原因
- 缓存
- 队列消费不及时
- 作用域未释放
慎将内存当做缓存
- 需要限定缓存对象的大小,加上完善的过期策略以防止内存无限制增长
- 尽量使用进程外的缓存,减少常驻内存的对象的数量,让垃圾回收更高效,进程之间可以共享缓存(Redis,Memcached)
关注队列状态
- 消费速度低于生产速度,将会形成堆积,需加强预警监控
内存泄漏排查
- v8-profiler 对 V8 堆内存抓取快照和对 CPU 进行分析
- node-heapdump 对 V8 堆内存抓取快照,用于事后分析
- node-memwatch
大内存应用
Node 提供 stream 模块用于处理大文件
var reader = fs.createReadStream('in.txt');
var writer = fs.createWriteStream('out.txt');
reader.on('data', function (chunk) {
writer.write(chunk);
});
reader.on('end', function () {
writer.end();
});
// 简写
var reader1 = fs.createReadStream('in.txt');
var writer1 = fs.createWriteStream('out.txt');
reader1.pipe(writer1);