gpt4 book ai didi

javascript - 在将大型json加载到firefox时占用大量内存

转载 作者:行者123 更新时间:2023-11-29 19:40:36 25 4
gpt4 key购买 nike

我们试图在Firefox 28上使用html5和indexeddb构建基于客户端的应用程序。AJAX请求使用json格式首次将大量数据加载到firefox中。每个json资源大约2MB(压缩),数据将通过IDBWrapper存储到indexeddb。

Firefox的内存使用量随着响应迅速增加。当我们运行大约12个响应时,firefox的内存将增长到大约1GB(总计3GB),有时会导致AJAX错误。成功加载后,内存将直接降至500MB或以下。

似乎在整个加载/存储过程中,firefox都没有机会进行GC,我们尝试在每个响应之间使用setTimeout,但这似乎是无奈的。

我的问题是,在加载大json时,还有其他方法可以减少firefox的内存使用吗?

编辑:
代码是这样的:

$.ajax({
url : URL['getData'],
dataType : "json",
data : {
startDate : _startDate,
endDate : _endDate,
format : "json"
},
async : true,
success : function(_data) {
_data = null;
// store to indexeddb
_callback();
},
error : function() {
setCurrentDataLabel('Error', 0);
}
});


我删除sotre到indexeddb的部分使之很简单。有趣的是,内存也迅速增加。但是,如果将 dataType : "json"更改为 dataType : "text",则内存使用量很小,GC显然正在运行。似乎Firefox在处理json时存在一些性能问题。

最佳答案

服务器端分页

如果所讨论的“服务器”正在运行某种编程语言/框架,并且如果您可以轻松地更改在该服务器上运行的代码,则最简单的方法就是@Coder在注释中所指。即:服务器端分页。

我将离开@Coder为“服务器分页”情况提供答案。

客户端流

另一方面,如果没有代码可以在服务器上进行更改(例如:它是由其他进程生成的静态JSON文件,并且只有一个简单的静态HTTP服务器),那么您可能想要采用我在评论中提到,即:让客户端进行流式传输。

在这种方法中:


您向服务器请求整个JSON文件(无论是2MB或更大),而不是使用XMLHttpRequest(AJAX),而是使用Firefox(StreamListener)中的本机平台API。
随着数据变得可从服务器读取,您可以使用所谓的JSON“ Pull Parser”来解析JSON到达的文本。
您解释拉取解析器发出的解析“事件”流,以便将数据增量写入本地存储(无论是数据库还是文件)。


注意1:

您不能在服务器端(显式或自动)使用GZIP编码,而仍然在客户端上进行流读取。您要么必须将服务器显式配置为仅提供未压缩的JSON,要么可以简单地使用Accept-Encoding:标头要求服务器不要向您发送压缩的内容(询问不存在的压缩方案,例如 )。

笔记2:

您还不能通过“内容” JavaScript(即:网络服务器提供的JavaScript内容)执行这种HTTP请求。您只能通过“特权” JavaScript(例如,在Firefox插件中)执行此操作。



沙盒HTTP请求

我不会提供发出请求本身的示例(它很大),但是您基本上可以从MDN的 Creating Sandboxed HTTP Connections页剪切并粘贴第一个(最简单的)示例。

在示例中,在 dont-compress-please回调中,它们只是将读取的文本添加到缓冲区(字符串)中,如下所示:

this.mData += scriptableInputStream.read(aLength);


取而代之的是,您希望您的提取解析器仅对新读取的文本进行“标记”,并为到目前为止已读取的数据的任何完全解析的部分发出事件(而不是在内存中构建表示从服务器读取的文本的字符串)。

JSON Pull解析器

“拉解析器”不会一次解析一个字符串(例如说 onDataAvailable);而是在收到的源文本的每个块上调用其 JSON.parse方法。解析器负责弄清楚它在输入流中的位置(使用“状态机”),以及何时开始或结束读取所谓的“ atom”(对于JSON,例如: tokenize(),< cc>, Array的结尾, Number的开头等),它将调用您提供的回调(或发出事件)来告知您。

因此,在您的情况下,假设JSON基本上是 ArrayObject。基本上,您应该忽略“ Array的开始”,然后对于每个“ Object的结束”,将单个 Array中的数据写入您的语言环境存储。这样一来,您一次存储在内存中的最大事情就是较大文件中的单个行/元素。

我发现了两个基于JavaScript的JSON Pull解析器:


Benejson +一个 example for node.js(易于适应StreamListener)
Clarinet


您需要配置您选择的解析器以“侦听”源文本中适当的开始/结束。

特权JavaScript

由于 Object界面具有特权,因此,如果您仍然希望此Web应用程序主要在Web上运行(并且仅具有脱机模式),则需要在Firefox插件中实现它。

此外,由于 Object回调调用了Pull Parser,因此也需要在附加组件内部将其实现为特权JavaScript。

实现这两个功能的最简单方法是实现 bootstrapped(又称“无重启”)Firefox插件,该插件将所需的功能“导出”到浏览器窗口中,以便您无特权的“内容” JavaScript代码可以使用它。

我之前已经回答了两次操作(涉及大量代码):


Expose File Writing to a Webpage with a Firefox Extension
Calling JavaScript function defined in XUL from external IFRAME

关于javascript - 在将大型json加载到firefox时占用大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23321384/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com