0

0

Nodejs 的内存限制到底是多少?

心靈之曲

心靈之曲

发布时间:2024-12-07 22:42:03

|

916人浏览过

|

来源于dev.to

转载

nodejs 的内存限制到底是多少?

熟练掌握 node.js api 可以让您快速入门,但深入了解 node.js 程序的内存占用可以让您走得更远。

让我们首先通过 process.memoryusage() 查看内存使用情况,每秒更新一次:

setinterval(() => { console.log('memory usage:', process.memoryusage()); }, 1000);

由于输出以字节为单位,因此不方便用户使用。让我们通过将内存使用量格式化为 mb:
来修饰它

function formatmemoryusageinmb(memusage) {
    return {
        rss: converttomb(memusage.rss),
        heaptotal: converttomb(memusage.heaptotal),
        heapused: converttomb(memusage.heapused),
        external: converttomb(memusage.external)
    };
}

const converttomb = value => {
    return (value / 1024 / 1024).tofixed(2) + ' mb';
};

const loginterval = setinterval(() => {
    const memoryusagemb = formatmemoryusageinmb(process.memoryusage());
    console.log(`memory usage (mb):`, memoryusagemb);
}, 1000);

现在,我们每秒都可以得到以下输出:

memory usage (mb): {
  rss: '30.96 mb', // the actual os memory used by the entire program, including code, data, shared libraries, etc.
  heaptotal: '6.13 mb', // the memory area occupied by js objects, arrays, etc., dynamically allocated by node.js
                      // v8 divides the heap into young and old generations for different garbage collection strategies
  heapused: '5.17 mb',
  external: '0.39 mb'
}

memory usage (mb): {
  rss: '31.36 mb',
  heaptotal: '6.13 mb',
  heapused: '5.23 mb',
  external: '0.41 mb'
}

我们都知道v8引擎的内存使用是有限的,不仅受到操作系统的内存管理和资源分配策略的限制,还受到其自身的设置的限制。

使用 os.freemem(),我们可以看到操作系统有多少可用内存,但这并不意味着 node.js 程序可以获取所有内存。

console.log('free memory:', os.freemem());

对于 64 位系统,node.js v8 默认最大旧空间大小约为 1.4gb。这意味着即使您的操作系统有更多可用内存,v8 也不会自动使用超过此限制的内存。

提示:可以通过设置环境变量或启动 node.js 时指定参数来更改此限制。例如,如果您希望 v8 使用更大的堆,可以使用 --max-old-space-size 选项:

node --max-old-space-size=4096 your_script.js

这个值需要根据你的实际情况和场景来设置。比如说,如果你有一台大内存的机器,独立部署,还有很多小内存的机器分布式部署,这个值的设置肯定会有所不同。

让我们通过无限地向数组填充数据来运行测试,直到内存溢出,看看什么时候会发生。

const array = [];
while (true) {
    for (let i = 0; i < 100000; i++) {
        array.push(i);
    }
    const memoryusagemb = formatmemoryusageinmb(process.memoryusage());
    console.log(`memory usage (mb):`, memoryusagemb);
}

这是我们直接运行程序时得到的结果。添加一段数据后,程序崩溃了。

memory usage (mb): {
  rss: '2283.64 mb',
  heaptotal: '2279.48 mb',
  heapused: '2248.73 mb',
  external: '0.40 mb'
}
memory usage (mb): {
  rss: '2283.64 mb',
  heaptotal: '2279.48 mb',
  heapused: '2248.74 mb',
  external: '0.40 mb'
}


#
# fatal error in , line 0
# fatal javascript invalid size error 169220804
#
#
#
#failuremessage object: 0x7ff7b0ef8070

困惑吗?不是限制1.4g吗?为什么使用2g以上?实际上,node.js 的 1.4gb 限制是 v8 引擎的历史限制,适用于早期的 v8 版本和某些配置。在现代 node.js 和 v8 中,node.js 会根据系统资源自动调整其内存使用情况。在某些情况下,它可能使用远超过 1.4gb 的空间,特别是在处理大型数据集或运行内存密集型操作时。

当我们将内存限制设置为 512m 时,当 rss 达到 996 mb 左右时就会溢出。

memory usage (mb): {
  rss: '996.22 mb',
  heaptotal: '993.22 mb',
  heapused: '962.08 mb',
  external: '0.40 mb'
}
memory usage (mb): {
  rss: '996.23 mb',
  heaptotal: '993.22 mb',
  heapused: '962.09 mb',
  external: '0.40 mb'
}

<--- last few gcs --->

[22540:0x7fd27684d000]     1680 ms: mark-sweep 643.0 (674.4) -> 386.8 (419.4) mb, 172.2 / 0.0 ms  (average mu = 0.708, current mu = 0.668) allocation failure; scavenge might not succeed
[22540:0x7fd27684d000]     2448 ms: mark-sweep 962.1 (993.2) -> 578.1 (610.7) mb, 240.7 / 0.0 ms  (average mu = 0.695, current mu = 0.687) allocation failure; scavenge might not succeed


<--- js stacktrace --->

fatal error: reached heap limit allocation failed - javascript heap out of memory

综上所述,更准确的来说,node.js 的内存限制是指堆内存限制,即 js 对象、数组等可以占用的最大内存,由 v8 分配。

堆内存的大小决定了node.js进程可以占用多少内存吗?不!继续阅读。

我可以将 3gb 文件放入 node.js 内存中吗?

我们在测试中看到,在程序崩溃之前,数组只能容纳 2gb 多一点。那么,如果我有一个 3gb 的文件,我不能把它一次性放入 node.js 内存吗?

TayCMS免费企业建站系统1.8 for PHP
TayCMS免费企业建站系统1.8 for PHP

由于精力有限,程序更新比较慢,请大家谅解,再次感谢支持taycms的朋友们,虽然比较慢,我们还是会一直更新下去的。谢谢您的关注。有什么建议可以到论坛提出,或者直接给我QQ留言。 2.0会有很多新功能,请关注官方论坛TayCMS 1.8 升级日志此版本修复了不少BUG1.更换图片切换JS , 不会再有错误提示2.增加资料下载模块3.更换默认模版,使程序功能和页面结构更清晰,方便参考制作模版4.修复留

下载

你可以的!

我们通过process.memoryusage()看到了一个外部内存,它被node.js进程占用,但没有被v8分配。只要你把3gb的文件放在那里,就没有内存限制。如何?您可以使用缓冲区。 buffer 是 node.js 的 c 扩展模块,使用 c 分配内存,而不是 js 对象和数据。

这是一个演示:

settimeout(()=>{
    let buffer = buffer.alloc(1024 * 1024 * 3000);
}, 3000)

即使你分配了3gb内存,我们的程序仍然可以顺利运行,而我们的node.js程序占用了超过5gb内存,因为这个外部内存不是node.js限制的,而是操作系统对分配内存的限制到线程(所以不能胡作非为,连buffer都会内存不足;本质是用streams来处理大数据)。

在 node.js 中,buffer 对象的生命周期与 javascript 对象相关联。当 javascript 对 buffer 对象的引用被删除时,v8 垃圾收集器会将该对象标记为可回收,但 buffer 对象的底层内存不会立即释放。通常,当调用 c 扩展的析构函数时(例如 node.js 中的垃圾回收过程),这部分内存会被释放。然而,这个过程可能与v8的垃圾收集不完全同步。

Memory Usage (MB): {
  rss: '2392.73 MB',
  heapTotal: '2392.57 MB',
  heapUsed: '2359.93 MB',
  external: '3000.41 MB'
}
Memory Usage (MB): {
  rss: '2392.75 MB',
  heapTotal: '2392.57 MB',
  heapUsed: '2359.94 MB',
  external: '3000.41 MB'
}
Memory Usage (MB): {
  rss: '2392.75 MB',
  heapTotal: '2392.57 MB',
  heapUsed: '2359.94 MB',
  external: '3000.41 MB'
}

总结:node.js 内存使用量由 js 堆内存使用量(由 v8 的垃圾回收决定) c 分配的内存组成

为什么堆内存分为新代和老代?

分代垃圾收集策略在现代编程语言的实现中非常普遍! ruby、.net 和 java 中都可以找到类似于分代垃圾收集的类似策略。当垃圾回收发生时,常常会导致“stop the world”的情况,这不可避免地影响程序性能。然而,这种设计是考虑到性能优化的。

  • 不同的对象寿命 在程序开发过程中,很大一部分变量是临时的,用于完成特定的本地计算任务。这样的变量更适合minor gc,即新一代gc。新一代内存中的对象主要通过scavenge算法进行垃圾回收。 scavenge 算法将堆内存一分为二,即 from 和 to(经典的空间换时间权衡。由于它们的生存时间较短,因此不会消耗大量内存)。

内存分配时,发生在 from 内。在垃圾回收期间,会检查 from 中的活动对象并将其复制到 to,然后释放非活动对象。在下一轮收集中,to 中的活动对象将被复制到 from,此时 to 会转变为 from,反之亦然。在每个垃圾收集周期中,from 和 to 都会交换。该算法在复制过程中仅复制存活对象,从而避免内存碎片的产生。
那么,变量的活跃度是如何确定的呢?可达性分析开始发挥作用。以以下对象为例:

  • globalobject:全局对象。
  • obj1:被globalobject直接引用的对象。
  • obj2:obj1引用的对象。
  • obj3:一个孤立的对象,没有任何其他对象的引用。

在可达性分析的背景下:

  • globalobject 作为根对象,本质上是可访问的。
  • obj1,由于被globalobject引用,也是可达的。
  • obj2 被 obj1 引用,因此也是可访问的。
  • 相比之下,obj3 由于缺少根对象或其他可到达对象的任何引用路径,因此被判定为不可到达,因此符合回收条件。

诚然,引用计数可以作为一种辅助手段。然而,在存在循环引用的情况下,它无法准确确定对象的真实活性。

在老年代内存中,对象通常不太活跃。但当老年代内存满了时,会通过mark-sweep算法触发老年代内存的清理(major gc)。

标记-清除算法包括两个阶段:标记和清除。在标记阶段,v8 引擎会遍历堆中的所有对象并标记存活的对象。在清扫阶段,仅清除未标记的对象。该算法的优点是,由于老年代中死亡对象的比例相对较小,因此清理阶段消耗的时间相对较少。但它的缺点是只清除而不压缩,可能会导致内存空间不连续,不方便为大对象分配内存。

这个缺点会导致内存碎片,需要使用另一种算法,mark-compact。该算法将所有存活对象移至一端,然后一举消灭边界右侧的无效内存空间,从而获得完整且连续的可用内存空间。它解决了 mark-sweep 算法可能导致的内存碎片问题,但代价是移动大量活动对象会花费更多时间。

如果您觉得这篇文章有用,请点赞。 :d

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

331

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

235

2023.10.07

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

398

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

525

2023.08.10

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

515

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.08.03

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
快速入门Node.JS全套完整版
快速入门Node.JS全套完整版

共83课时 | 8.5万人学习

nodejs开发基础教程
nodejs开发基础教程

共15课时 | 4.5万人学习

JavaScript设计模式视频教程
JavaScript设计模式视频教程

共28课时 | 5.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号