Node.js 作密集型运算,或者所操做的数组、对象自己较大时,容易出现内存溢出的问题,这是因为 Node.js 的运行环境依赖 V8 引擎致使的。若是常常有较大数据量运算等操做,须要对 Node.js 运行环境限制有充分的了解。javascript
做者简介:koala,专一完整的 Node.js 技术栈分享,从 JavaScript 到 Node.js,再到后端数据库,祝您成为优秀的高级 Node.js 工程师。【程序员成长指北】做者,Github 博客开源项目 github.com/koala-codin…java
下面是咱们在Node.js应用中常常遇到的两类内存溢出问题:node
示例1:当咱们须要批量处理一些数据(如:更新用户某项信息)时,咱们可能须要一个较大的for或while循环来完成全部的数据的更新,如:git
for (var i = 0; i < 10000000; i++) {
((i) => {
var site = {};
site.name = 'koala';
site.domain = '程序员成长指北';
// 这里是一个保存或更新等操做
setTimeout(()=>{
console.log(i, site);
}, 0)
})(i)
}
复制代码
示例2:对象须要频繁的建立/销毁,或操做对象自己较大,如:程序员
var sites = [];
for (var x=0;x<5000;x++){
var site=[];
for (var y=0;y<5000;y++){
site = [y, 'koala', '程序员成长指北'];
sites.push(site);
}
}
复制代码
上面两类操做都会出现相似如下错误:github
<--- Last few GCs --->
……
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
Abort trap: 6
复制代码
咱们都知道,V8是 Google 在 Chrome 浏览器中使用的 JavaScript 引擎。而在浏览器环境中,运算通常不须要多大内存。 V8 对每一个进程分配的运行内存,在32位系统中约为700MB,而在64位系统中约为1.4GB。数据库
Node.js 程序之因此会出内存溢出的状况,能够分为三方面的缘由:后端
在示例1中,每次运算所需的内存量并不大,但因为for循环,形成V8内存不能及时释放。随着程序运行时候的增长,内存占用量会愈来愈大,并最终致使内存的溢出。数组
在示例2中,可能所建立对象自己并无超过内存限制。可是除对象自己外:建立对象、对象引用、Node.js程序自己等都须要内存空间,这样就很容易致使内存的溢出。浏览器
在Node.js应用开发过程当中,了解V8内存分配和JavaScript语言限制是Node程序的基本素质。咱们应该在应用中权衡利弊,综合考虑内存与程序的运行效率。如下几点防止内存溢出的建议:
await将代码执行顺序变为了同步。这样可使 V8 得到内存回收的机会,有效解决过多事件堆积形成的内存溢出。 咱们可使用await方法处理:
async function dbFuc() {
for (let i = 0; i < 10000000; i++) {
var site = {};
site.name = 'koala';
site.domain = '程序员成长指北';
// 这里是一个保存或更新等操做
await console.log(i, site);
}
}
dbFuc();
复制代码
每次循环V8都会回收内存一次,所以内存不会再溢出。但这样作必然会形成运行效率的下降,而应该在速度在安全之间平衡,控制好循环的安全次数。 说明:实际开发中,上面这种虽然解决了内存溢出,可是仍然会形成进程阻塞,能够开启一个进程/线程来解决阻塞问题(具体能够看个人这篇文章《深刻理解Node.js 进程与线程(8000长文完全搞懂)》)
Node.js提供了一个程序运行参数--max-old-space-size
,能够经过该参数指定V8所占用的内存空间,这样能够在必定程度上避免程序内存的溢出。 如,咱们能够在运行示例2程序时指定使用4G的内存: node --max-old-space-size=4096 app
Node.js程序所使用的内存分为两类:
(注: fs 和 stream 这两个模块我在 Node 进阶系列文章中已经详细介绍了, 这里就不赘述)
在程序容许的状况下,应该将数据保存在Buffer中,而不是转换成字符串等JS对象,这样能够避免V8内存的过多占用。(buffer能够看一下这篇文章《Node进阶-探究不在V8堆内存中存储的Buffer对象》)
require时,exports和module.exports的区别你真的懂吗