我是否达到了浏览器可以处理的JavaScript对象大小的限制?

Mat*_*all 63 javascript memory arrays

<script>在我的HTML中嵌入了一个大型数组,就像这样(没什么好惊讶的):

<script>
    var largeArray = [/* lots of stuff in here */];
</script>
Run Code Online (Sandbox Code Playgroud)

在此特定示例中,阵列具有210,000个元素.这远远低于理论最大值2 31 - 4个数量级.这是有趣的部分:如果我将数组的JS源保存到文件中,那么该文件大于44兆字节(确切地说是46,573,399字节).

如果您想亲眼看看,可以从GitHub下载.(那里的所有数据都是罐装的,所以很多都是重复的.生产中不会这样.)

现在,我真的不担心提供那么多数据.我的服务器gzips它的响应,所以它真的不需要花费很长时间才能通过网络获取数据.但是,一旦加载,页面就会出现令人讨厌的趋势,导致浏览器崩溃.我在IE中根本没有测试(这是一个内部工具).我的主要目标是Chrome 8和Firefox 3.6.

在Firefox中,我可以在控制台中看到一个相当有用的错误:

Error: script stack space quota is exhausted

在Chrome中,我只是得到了悲伤标签页:

在此输入图像描述

已经切入了追逐

  • 对于我们现代的"高性能"浏览器来说,这真的太多了吗?
  • 有什么我可以做*优雅地处理这么多的数据?

顺便说一句,我能够在Chrome中启用此功能(阅读:不会崩溃选项卡).我真的认为Chrome至少是由更强硬的东西制成的,但显然我错了......


编辑1

@Crayon:我不想证明我为什么要立即将这么多数据转储到浏览器中.简短版本:要么解决这个问题(当然不是那么容易),要么我必须解决一大堆其他问题.我现在选择更简单的方法.

@various:现在,我并不是特别想找到减少数组中元素数量的方法.我知道我可以实现Ajax分页或者你有什么,但是在其他方面它会为我引入一系列问题.

@Phrogz:每个元素看起来像这样:

{dateTime:new Date(1296176400000),
 terminalId:'terminal999',
 'General___BuildVersion':'10.05a_V110119_Beta',
 'SSM___ExtId':26680,
 'MD_CDMA_NETLOADER_NO_BCAST___Valid':'false',
 'MD_CDMA_NETLOADER_NO_BCAST___PngAttempt':0}
Run Code Online (Sandbox Code Playgroud)

@Will:但是我的计算机配备了4核处理器,6 GB RAM,超过半TB的磁盘空间......我甚至都没有要求浏览器快速完成这项工作 - 我只想问因为它可以工作!


编辑2

任务完成!

通过JuanGuffa的现场建议,我能够让这个工作!似乎问题只是解析源代码,而不是在内存中实际使用它.

总结胡安答案的评论泥潭:我不得不将我的大阵列分成一系列较小的阵列,然后是Array#concat()它们,但这还不够.我必须将它们分别var发表.像这样:

var arr0 = [...];
var arr1 = [...];
var arr2 = [...];
/* ... */
var bigArray = arr0.concat(arr1, arr2, ...);
Run Code Online (Sandbox Code Playgroud)

致所有为解决这个问题做出贡献的人:谢谢.第一轮对我来说!


*除了显而易见的事情:向浏览器发送更少的数据

Jua*_*des 82

这是我要尝试的:你说它是一个44MB的文件.这肯定需要超过44MB的内存,我猜这需要超过44MB的RAM,也许是半场演出.您是否可以减少数据直到浏览器不崩溃并查看浏览器使用多少内存?

即使只在服务器上运行的应用程序也能很好地读取44MB文件并将其保存在内存中.说了这么多,我相信浏览器应该能够处理它,所以让我运行一些测试.

(使用Windows 7,4GB内存)

第一次测试 我把阵列切成两半,没有问题,使用80MB,没有崩溃

第二次测试 我将数组分成两个独立的数组,但仍然包含所有数据,使用160Mb,没有崩溃

第三次测试 由于Firefox说它没有堆栈,问题可能是它无法立即解析数组.我创建了两个独立的数组,arr1,arr2然后做了arr3 = arr1.concat(arr2); 它运行良好,仅使用稍多的内存,大约165MB.

第四次测试我正在创建其中7个阵列(每个22MB)并将它们连接起来测试浏览器限制.页面完成加载大约需要10秒钟.内存高达1.3GB,然后又回落到500MB.所以是的铬可以处理它.它只是不能一次解析它,因为它使用某种递归,因为控制台的错误消息可以注意到.

回答创建单独的数组(每个少于20MB),然后连接它们.每个数组都应该在它自己的var语句中,而不是使用单个var进行多个声明.

我仍然会考虑只获取必要的部分,这可能会使浏览器变得迟钝.但是,如果这是一项内部任务,那应该没问题.

最后一点:您没有达到最大内存级别,只是最大解析级别.


Guf*_*ffa 13

是的,要求浏览器太多了.

如果数据已经是数据,那么这些数据将是可管理的,但它还不是数据.考虑到浏览器必须解析那个巨大的源代码块,同时检查语法是否会加起来.解析成有效代码后,代码必须运行才能生成实际数组.

因此,所有数据将同时存在于(至少)两个或三个版本中,每个版本都有一定的开销.由于数组文字是单个语句,因此每个步骤都必须包含所有数据.

将数据划分为几个较小的数组可能会使浏览器更容易.

  • 这意味着,如果你礼貌地问,问不是太多了:) (6认同)

Mat*_*ský 5

你真的需要所有数据吗?你不能只使用AJAX流式传输当前需要的数据吗?与谷歌地图类似 - 您无法将所有地图数据放入浏览器的内存中,它们只显示您当前看到的部分.

请记住,在浏览器的内部表示中,40兆的硬数据可以膨胀得更多.例如,JS解释器可以使用散列表来实现数组,这会增加额外的内存开销.此外,我希望浏览器同时存储源代码和JS内存,这仅仅是数据量的两倍.

JS旨在提供客户端UI交互,而不是处理大量数据.

编辑:

顺便说一下,你真的认为用户会喜欢下载40兆字节的代码吗?仍有许多用户使用宽带互联网.并且将暂停执行脚本,直到下载所有数据.

EDIT2:

我查看了数据.该数组肯定会表示为哈希表.此外,许多项目都是对象,需要参考跟踪...这是额外的内存.

我想如果它是原始数据的简单向量,性能会更好.

编辑3:数据当然可以简化.它的大部分是重复的字符串,可以用某种方式编码为整数或其他东西.另外,我的Opera在显示文本时遇到了麻烦,更不用说解释它了.

EDIT4:忘记DateTime对象!使用unix时代的时间戳或字符串,但不使用对象!

编辑5:您的处理器无关紧要,因为JS是单线程的.而且你的RAM也无关紧要,大多数浏览器都是32位,所以它们不能使用大部分内存.

EDIT6:尝试将数组索引更改为顺序整数(0,1,2,3 ......).这可能会使浏览器使用更高效的数组数据结构.您可以使用常量有效地访问数组项.这将通过巨大的块来减少阵列大小.


Bit*_*ter 5

尝试使用Ajax作为JSON页面检索数据.我不知道确切的大小,但我已经能够以这种方式将大量数据提取到Google Chrome中.