Javascript 中数组的最大大小

IT技术 javascript arrays
2021-01-24 12:22:12

上下文:我正在构建一个读取 rss 提要并在后台更新/检查提要的小站点。我有一个数组来存储要显示的数据,另一个数组存储已显示的记录的 ID。

问题:在事情开始变慢或缓慢之前,一个数组可以在 Javascript 中保存多少项。我没有对数组进行排序,而是使用 jQuery 的 inArray 函数进行比较。

该网站将保持运行和更新,并且浏览器不太可能经常重新启动/刷新。

如果我应该考虑从数组中清除一些记录,那么在限制之后删除一些记录的最佳方法是什么,例如 100 个项目。

6个回答

“它变得缓慢”之前的最大长度完全取决于您的目标机器和您的实际代码,因此您需要在该(那些)平台上进行测试以查看可接受的内容。

但是,根据 ECMA-262 第 5 版规范,由于ToUint32抽象操作,数组的最大长度受无符号 32 位整数的约束,因此可能的最长数组可能有 2 32 -1 = 4,294,967,295 = 42.9 亿个元素.

@Barkermn01,64 位浏览器还有很多其他改进。请记住,成为 javascript 解释器并不是浏览器所做的唯一事情。
2021-03-17 12:22:12
沃泽没想到会这么高。好的很好,我想我会没事的!
2021-03-22 12:22:12
嗯,不错,刚刚读到一个令人敬畏的 64 位浏览器在燃烧时毫无意义,
2021-03-23 12:22:12
@Barkermn01:ECMA-262 第 5 版规范使用抽象操作ToUint32在任何修改数组长度的操作上检查数组的长度,因此我认为机器(或 Web 浏览器)的底层架构无关紧要。
2021-03-26 12:22:12
实际上一个数组最多可以有 4294967295 (2^31-1) 个元素。参见stackoverflow.com/a/12766547/396458
2021-04-08 12:22:12

无需修剪数组,只需将其作为循环缓冲区寻址(索引 % maxlen)。这将确保它永远不会超过限制(实现循环缓冲区意味着一旦到达末尾,您将再次返回到开头 - 不可能超出数组的末尾)。

例如:

var container = new Array ();
var maxlen = 100;
var index = 0;

// 'store' 1538 items (only the last 'maxlen' items are kept)
for (var i=0; i<1538; i++) {
   container [index++ % maxlen] = "storing" + i;
}

// get element at index 11 (you want the 11th item in the array)
eleventh = container [(index + 11) % maxlen];

// get element at index 11 (you want the 11th item in the array)
thirtyfifth = container [(index + 35) % maxlen];

// print out all 100 elements that we have left in the array, note
// that it doesn't matter if we address past 100 - circular buffer
// so we'll simply get back to the beginning if we do that.
for (i=0; i<200; i++) {
   document.write (container[(index + i) % maxlen] + "<br>\n");
}
这个想法是实现一个环形缓冲区,所以是的 - 你故意“忘记”旧数据(这就是环形缓冲区的用途),这就是提问者所要求的。
2021-03-13 12:22:12
聪明的想法,但这样做可能会覆盖数据,混淆索引,并可能导致奇怪的行为。
2021-03-23 12:22:12
我只是无聊地点击 SO 并找到了这个回复。喜欢根据需要覆盖索引的技术。
2021-03-30 12:22:12

就像@maerics 所说的,您的目标机器和浏览器将决定性能。

但是对于一些真实世界的数字,在我 2017 年的企业 Chromebook 上,运行以下操作:

console.time();
Array(x).fill(0).filter(x => x < 6).length
console.timeEnd();
  • x=5e4 需要 16ms,足够 60fps
  • x=4e6 需要 250 毫秒,这很明显但没什么大不了的
  • x=3e7 需要 1300 毫秒,这很糟糕
  • x=4e7 需要 11000ms 并分配额外的 2.5GB 内存

所以大约 3000 万个元素是一个硬上限,因为 javascript VM 在 4000 万个元素时掉下悬崖并且可能会导致进程崩溃。


编辑:在上面的代码中,我实际上是用元素填充数组并循环遍历它们,模拟应用程序可能想要对数组执行的最少操作。如果您只是运行,Array(2**32-1) 您将创建一个稀疏数组,该数组更接近于一个空 JavaScript 对象,其长度类似于{length: 4294967295}. 如果您真的尝试使用所有这 40 亿个元素,您肯定会导致 javascript 进程崩溃。

@SlawomirBrys 你跑了什么?你最终会撞上悬崖吗?在节点 v15.3.0,核心 i9 的 macbook 上,我看到相同的悬崖:time node -e "console.log(Array(4e7).fill(0).filter(x=>x<6).length)"需要 9 秒,而长度3e7需要 1.1 秒。切换回 v12.17.0 我仍然得到同样的悬崖,除了慢版本需要 11 秒。
2021-03-13 12:22:12
我刚刚使用了new Array(size * size)where sizeis 10000,所以我在数组中获得了 100M 个元素。通过 2 个for循环遍历数组并为数组的每个元素分配一些值,大约需要 950 毫秒。我没有使用fill()也没有filter()函数,似乎开销是由filter()函数引起的
2021-03-19 12:22:12
我已经尝试过 Node v12.17.0,Intel Core i7,1 亿个元素在大约 2 秒内占用了 2.3GB 的内存,大约 12% 的 CPU,没有任何崩溃。
2021-03-30 12:22:12
@SlawomirBrys 对稀疏数组进行了编辑
2021-03-31 12:22:12

你可以尝试这样的事情来测试和修剪长度:

http://jsfiddle.net/orolo/wJDXL/

var longArray = [1, 2, 3, 4, 5, 6, 7, 8];

if (longArray.length >= 6) {
  longArray.length = 3;
}

alert(longArray); //1, 2, 3

最终使用切片,因为我需要从数组的开头进行修剪,谢谢。
2021-03-17 12:22:12

我已经构建了一个性能框架来操作和绘制数百万个数据集,即使这样,javascript 计算延迟也只有几十毫秒。除非您担心超出数组大小限制,否则我认为您无需担心太多。