【问题标题】:Weird memory usage on Node.jsNode.js 上奇怪的内存使用情况
【发布时间】:2013-01-28 07:42:40
【问题描述】:

这个简单的代码将 100 万个字符串(100 个字符长度)存储在一个数组中。

function makestring(len) {
    var s = '';
    while (len--) s = s+'1';
    return s;
}

var s = '';
var arr = [];
for (var i=0; i<1000000; i++) {
    s = makestring(100);
    arr.push(s);
    if (i%1000 == 0) console.log(i+' - '+s);
}

当我运行它时,我得到这个错误:

(...)
408000 - 1111111111111111111 (...)
409000 - 1111111111111111111 (...)
FATAL ERROR: JS Allocation failed - process out of memory

奇怪的是 100 万 * 100 只是 100 兆字节。

但是如果我将s = makestring(100); 移到循环之外...

var s = makestring(100);
var arr = [];
for (var i=0; i<1000000; i++) {
    arr.push(s);
    if (i%1000 == 0) {
        console.log(i+' - '+s);
    }
}

这执行没有错误!

为什么?如何在节点中存储 100 万个对象?

【问题讨论】:

    标签: node.js memory


    【解决方案1】:

    在将字符串生成移出循环的那一刻,您基本上只需创建一个字符串并将其推入数组一百万次。

    然而,在数组内部,只使用了指向原始字符串的指针,这比将字符串保存一百万次要少得多。

    【讨论】:

      【解决方案2】:

      您的第一个示例构建 1000000 字符串。

      在第二个示例中,您使用相同的字符串对象并将其添加到数组1000000 次。 (它不是复制字符串;数组的每个条目都指向同一个对象)

      V8 做了很多事情来优化字符串的使用。例如,字符串连接(在大多数情况下)比您想象的要便宜。它通常不会构建一个全新的字符串,而是选择在幕后以链表的方式将它们连接起来。

      【讨论】:

      • 无论如何,1 Millon 字符串 (~100MB) 不应该吃掉所有内存
      • 您的数学已关闭。一方面,V8 的每个字符串都有相当多的记账开销(我不确定有多少——可能每个字符串大约 10 个字节)。我也相当确定 V8 默认以 UTF-16 存储字符串(每个字符 2 个字节)。
      • 如果您想要一种更节省内存的方式来存储大量数据,请查看Node's Buffer class。
      • Nevir,即使开销是每个字符串 500 字节,100 万也就是 600 MB,远低于内存限制。
      • 请注意,在您的示例中,您的 makestring 函数每次都会创建 100 新字符串(每个都有一定的开销),并且 V8 可能不会将它们扁平化为一个对象。很有可能您的示例实际上构建了 1000000 * 100 字符串对象。
      猜你喜欢
      • 2020-06-24
      • 1970-01-01
      • 2015-02-27
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多