Node.js内存溢出时如何处理?

640?wx_fmt=gif

Node.js 做密集型运算,或者所操作的数组、对象本身较大时,容易出现内存溢出的问题,这是由于 Node.js 的运行环境依赖 V8 引擎导致的。如果经常有较大数据量运算等操作,需要对 Node.js 运行环境限制有充分的了解。 

本文涵盖

  1. 内存溢出问题

  2. 为什么会内存溢出

  • 2.1 V8内存分配机制

  • 2.2 内存溢出的原因

如何解决内存溢出问题

1. 内存溢出问题

下面是我们在Node.js应用中经常遇到的两类内存溢出问题:

密集型运算

示例1:当我们需要批量处理一些数据(如:更新用户某项信息)时,我们可能需要一个较大的forwhile循环来完成所有的数据的更新,如:

 
 

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);

    }

}


上面两类操作都会出现类似以下错误:

<--- Last few GCs --->
……
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
Abort trap: 6


2. 为什么会内存溢出

2.1 V8内存分配机制

我们都知道,V8是 Google 在 Chrome 浏览器中使用的 JavaScript 引擎。而在浏览器环境中,运算一般不需要多大内存。

V8 对每个进程分配的运行内存,在32位系统中约为700MB,而在64位系统中约为1.4GB。


2.2 内存溢出的原因

Node.js 程序之所以会出内存溢出的情况,可以分为三方面的原因:1. V8本身分配的内存较小、2. JavaScript语言本身限制、3. 程序员使用不当。

示例1中,每次运算所需的内存量并不大,但由于for循环,造成V8内存不能及时释放。随着程序运行时候的增加,内存占用量会越来越大,并最终导致内存的溢出。

示例2中,可能所创建对象本身并没有超过内存限制。但是除对象本身外:创建对象、对象引用、Node.js程序本身等都需要内存空间,这样就很容易导致内存的溢出。


3. 解决内存溢出问题

在Node.js应用开发过程中,了解V8内存分配和JavaScript语言限制是Node程序的基本素质。我们应该在应用中权衡利弊,综合考虑内存与程序的运行效率。以下几点防止内存溢出的建议:

1. 使用 async/await防止事件堆积,变为同步操作 

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长文彻底搞懂))

2. 增加V8内存空间

Node.js提供了一个程序运行参数--max-old-space-size,可以通过该参数指定V8所占用的内存空间,这样可以在一定程度上避免程序内存的溢出。

如,我们可以在运行示例2程序时指定使用4G的内存:

node --max-old-space-size=4096 app


3. 使用非V8内存

Node.js程序所使用的内存分为两类:

在程序允许的情况下,应该将数据保存在Buffer中,而不是转换成字符串等JS对象,这样可以避免V8内存的过多占用。(buffer可以看一下这篇文章Node进阶-探究不在V8堆内存中存储的Buffer对象

❤️ 看完三件事

如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:

  1. 点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)

  2. 关注我的博客 https://github.com/koala-coding/goodBlog,让我们成为长期关系

  3. 关注公众号「程序员成长指北」,持续为你推送优质精选好文,也可以加我为好友哦。640?wx_fmt=jpeg

在看点这里2_04.png

640?wx_fmt=gif640?wx_fmt=png

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值