我当时正在做一个大Map https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map在 Node.js v11.9.0 中,它一直失败,并显示“致命错误:无效的表大小分配失败 - JavaScript 堆内存不足”。我的映射的键和值不应该接近节点堆大小的大小,因此我尝试制作一个映射并向其中插入数字键和值:
var N = Math.pow(2, 26);
var map = new Map();
for (var i = 0; i < N; i++) {
map.set(i, i + 1);
if (i % 1e5 === 0) { console.log(i / 1e6); }
}
该程序在插入大约 1660 万个条目后使 Node 崩溃。该数字似乎可疑地接近 2^24,因此将上面的日志记录替换为if (i > 16777200) { console.log(i); }
,我看到程序在成功打印“16777215”后立即崩溃,它比 2^24 少了 1。
问题。Node 中的条目数量是否有记录限制?Map
接近2^24?有什么办法可以提高这个限制吗?
(注意:运行节点为node --max-old-space-size=4096
并不能防止崩溃,因为 Node 使用的 RAM 远远小于 4 GB。)
(注意 2.我不认为这是哈希冲突问题,因为在我的实际代码中,映射包含(短的)字符串而不是数字。)
(注意 3. 在 Firefox 的 JavaScript 控制台中运行上述程序并不会杀死 Firefox——Firefox 不断添加超过 3000 万的条目。然而,Chrome 就像 Node 一样崩溃。所以这可能是 V8 的限制。)
V8 开发者在这里。我可以确认 2^24 是 a 中的最大条目数Map
。这不是一个错误,这只是实现定义的限制。
该限制由以下因素确定:
- The
FixedArray
的后备存储Map
最大大小为 1GB(与总体堆大小限制无关)
- 在 64 位系统上,这意味着 1GB / 8B = 2^30 / 2^3 = 2^27 ~= 每个最大元素 134M
FixedArray
- A
Map
每个条目需要3个元素(key、value、下一个bucket链接),并且最大负载系数为50%(以避免多次bucket碰撞造成的减速),其容量必须是2. 2^27的幂/ (3 * 2) 向下舍入到 2 的下一个幂是 2^24,这是您观察到的极限。
FWIW,一切都有限制:除了最大堆大小之外,还有一个最大堆大小String
长度,最大Array
长度,最大ArrayBuffer
长度,最大BigInt
这些限制中的任何一个都可能存在争议,有时提高它们是有意义的,但这样的限制仍然存在。我突然不知道如何才能将这个特定限制提高两倍,而且我也不知道两倍是否足以满足您的期望。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)