首页 web前端 js教程 Node.js 的内存限制到底是多少?

Node.js 的内存限制到底是多少?

Dec 25, 2024 am 04:35 AM

What Exactly Is the Memory Limit of Node.js?

熟练掌握 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 内存吗?

你可以的!

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

这是一个演示:

setInterval(() => { console.log('Memory Usage:', process.memoryUsage()); }, 1000);
登录后复制
登录后复制

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

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

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);
登录后复制
登录后复制

总结: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

以上是Node.js 的内存限制到底是多少?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

前端开发中如何实现类似 VSCode 的面板拖拽调整功能? 前端开发中如何实现类似 VSCode 的面板拖拽调整功能? Apr 04, 2025 pm 02:06 PM

探索前端中类似VSCode的面板拖拽调整功能的实现在前端开发中,如何实现类似于VSCode...

See all articles