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

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

831

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

737

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

733

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16925

2023.08.03

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

10

2026.01.12

热门下载

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

精品课程

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

共83课时 | 8.2万人学习

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

共15课时 | 4.5万人学习

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

共28课时 | 5.2万人学习

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

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