javascript - Nodejs中的数组内存分配

标签 javascript arrays node.js v8

我正在处理一个巨大的数组,

它包含约 200,000 个元素。基本上它是一个字符串数组。每个字符串的长度约为 50 个字符。环顾四周后,我发现 1 个字符需要 2 个字节,即 1 个元素需要 100 个字节。

因此,总内存分配总计应为 200,000 * 100 = ~20 MB

object-sizeof , js-sizeof , sizeof似乎实现了相同的逻辑。

但是考虑一下这个片段,

process.memoryUsage();
const paths = getAllFilePaths();
process.memoryUsage();

获取数组之前的输出,

external:25080
heapTotal:31178752
heapUsed:10427896 //10 MB
rss:51761152

获取数组后输出,

external:16888
heapTotal:173539328
heapUsed:134720896 //134 MB
rss:204070912

这比 heapUsed 增加了约 124MB。

实现getAllFilePaths():

const getAllFilePaths = function (_path, paths = []) {

    fs.readdirSync(_path).forEach(name => {
        const stat = fs.lstatSync(joinPath(_path, name))
        if (stat.isDirectory()) {
            getAllFilePaths(joinPath(_path, name), paths);
            return;
        }

        paths.push(joinPath(_path, name));
    });

    return paths;
};

为什么使用了这么多内存?这是期望的行为还是 getAllFilePaths() 函数可能会泄漏内存?

最佳答案

V8 开发人员在这里。我想到两点来解释您的期望和测量之间的差异:

(1) 字符串数组需要的内存不仅仅是字符串的字符。在内存中,字符串对象有一个 header ,在 64 位系统上占用 16 个字节(一个指针大小的 [1]“形状”指针加上两个用于哈希和长度的 32 位字段)。根据字符串的具体构造方式,它们也可能在内部使用不同的表示形式;标题+字符是最简单的形式。此外,数组本身为每个元素都有一个指针大小的条目,至少再添加 200,000 * 8 字节 = 1.5MB——动态增长的数组在必须增长时会过度分配,这样它们就不必增长每次添加,如果数组不幸在过度分配后立即停止增长,这可能会浪费空间。

(2) AFAIK process.memoryUsage() 只是返回当前堆使用统计信息,其中可能包含先前操作留下的垃圾。要确定某些内容的内存消耗,建议在每次测量之前显式触发完整的 GC 周期。具体来说:使用 --expose-gc 启动 Node,并在每个 process.memoryUsage() 之前调用 global.gc()

为了完整起见,我将提到:字符串每个字符可以占用 1 或 2 个字节,具体取决于其内容。对于每个单独的字符串,每个字符占用相同的数量,因此单个非 ASCII 字符会强制整个字符串为两个字节。对于嵌入器提供的字符串(如文件名),嵌入器还必须配合以支持一字节优化;我不知道Node的文件API是否这样做。

[1] “指针大小”现在意味着 64 位 = 8 个字节;随着“pointer-compression ”在 V8 8.0 中可用,它会缩小到 4 个字节(如果您选择部署指针压缩版本)。

关于javascript - Nodejs中的数组内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59607913/

相关文章:

javascript - csv 到 javascript 删除第一行?

javascript - 如何显示 Redactor 富文本/html 编辑器的字符数/字数?

java - 如何在没有java utils的情况下比较两个字符串数组

node.js - 分离 Node 串口获取的数据

javascript - Node 和 Socket.IO - 私有(private)聊天(一对一)

javascript - 从 pyqt QWebEngineView 启动 javascript 函数

javascript - 使用 AngularFire 简化 Angular Controller 发布到 Firebase

php - 基于数组在mysql表中添加多行

Python从第一个开始创建第二个数组

node.js - 测试 Mocha 中的预期超时