[翻译] 指南:如何在Node.js查看内存使用情况?

2021-08-27大约17分钟

您将学到什么

  • 如何获取有关Node.js进程的内存的信息

  • Node.js如何组织内存

要求

要继续学习,您需要对Javascript和Node.js有基本的了解。

Node.js如何组织内存?

一篇文章难以把Node.js的内存使用机制全部解释清楚,我们主要关心的是堆(Heap)的使用。

堆(Heap)是一个在内存中存储对象的区域,包含字符串和闭包等对象。这是让我们的代码发挥魔术的地方。

Node.js进程把所有的内存占用放到驻留集(Resident Set)中,而堆只是其中的一部分。驻留集中,除了堆,还有JavaScript代码(在“代码段Code segment”内)和所有的变量(在“栈Stack”中)。

下图可以更好地阐明这个概念:

图片

上图中,Code Segment里的JavaScript代码是Node.js加载的所有的代码模块,占用空间跟我们的代码量有关,通常都不是问题,不需要关心;Stack里面的变量也随着变量在程序中的作用域变化进入或弹出,除非少数几种错误情况,内存占用也不是问题。我们主要还是关心堆Heap里使用的内存大小,称之为Used heap

查询Node.js堆

我们知道驻留集是什么,我们也知道堆是我们要寻找的东西。现在,我们需要找出给定的Node.js进程使用了​​多少堆内存,具体如何做呢?

process是一个全局Node.js对象,其中包含有关当前Node.js进程的信息,并且它提供了我们正在寻找的内容:memoryUsage()方法。

memoryUsage返回具有各种信息的对象:rss,heapTotal,heapUsed,external:

  • rss代表Resident Set Size,它是分配给进程执行的总内存 。

  • heapTotal是分配的堆的总大小 。

  • heapUsed是在执行过程中使用的实际内存。根据文档,外部是“ C++对象绑定到由V8管理的JavaScript对象”使用的内存

有了这些知识,我们准备看到一些示例。

试验一个小型数组的reverse()内存使用情况

在我们的第一个例子中,我们将看到多少内存使用的一个非常基本的方法:reverse()。reverse是一个数组方法:它接受一个数组并反转其内容。

创建一个名为的新文件reverse_node.js

const arr = [1, 2, 3, 4, 5, 6, 9, 7, 8, 9, 10];
arr.reverse();
const used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`The script uses approximately ${Math.round(used * 100) / 100} MB`);

现在,如果您运行此脚本,应该会看到以下输出:

This script uses approximately 3.6 MB of memory

在上面的示例中,我从中选择了属性heapUsed,process.memoryUsage()但如果您自己运行process.memoryUsage(),则可以访问上一部分中列出的其他属性。例如,通过运行:

const arr = [1, 2, 3, 4, 5, 6, 9, 7, 8, 9, 10];
arr.reverse();
const used = process.memoryUsage();
for (let key in used) {
  console.log(`${key} ${Math.round(used[key] / 1024 / 1024 * 100) / 100} MB`);
}

您将看到以下输出:

rss 25.63 MB

heapTotal 5.49 MB

heapUsed 3.6 MB

external 0.01 MB

这不是衡量Node.js中内存消耗的最准确方法,但是至少您可以完成工作。

进行检测时,还有更多注意事项,特别是您应该考虑Node.js垃圾收集器。除此之外,memoryUsage至少可以给您了解给定脚本/进程占用了多少内存。

让我们继续另一个例子!

试验一个大型数组的reverse()内存使用情况

现在测试一个很大的数组怎么样?

在您的目录内创建一个新文件,名为reverse_node_bigArray.js

let arr = Array(1e6).fill("some string");
arr.reverse();
const used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`The script uses approximately ${used} MB`);

Array(1e6)创建一个长度为1百万的空数组。然后,该fill()方法用字符串填充数组的每个位置。至此,我们有了一个包含一百万个元素的数组。

通过运行新脚本,您应该看到以下输出:

This script used approximately 11.23 MB

如果我们增加数组的大小,事情将变得越来越有趣。在脚本中,将以下行:

let arr = Array(1e6).fill("some string");

更改为:

let arr = Array(1e8).fill("some string");

Array(1e8)创建一个长度为1亿的空数组。同样,该fill()方法用字符串填充数组的每个位置。

至此,我们有了一个数组,其中包含1亿个元素,再次运行该脚本,您将看到内存使用率如何增加:

This script uses approximately 1278.83 MB

现在检查您的代码,看看是否可以优化某些功能!

从这往哪儿走

我们已经看到了如何测量Node.js进程的内存使用情况。请记住,对于最常见的需求,该memoryUsage()方法就足够了,但是如果您要调查Node.js应用程序中的内存泄漏,则需要了解更多知识。