Javascript 将大量数据加载到内存-最有效的方法?
我有一个基于网络的文档搜索/查看系统,我正在为客户开发。该系统的一部分是一个搜索系统,允许客户端搜索文档中包含的术语。我已经创建了必要的搜索数据文件,但是有很多数据需要加载,加载所有数据需要8-20秒。根据需要搜索的文档,数据被分为40-100个文件。每个文件的大小在40-350kb之间 此外,此应用程序必须能够在本地文件系统上运行,以及通过Web服务器运行 当网页加载时,我可以生成需要加载的搜索数据文件列表。必须先加载整个列表,才能将网页视为可用 有了序言,让我们看看我现在是怎么做的 在知道整个网页已加载后,我调用loadData()函数 这样做的目的是按顺序处理一组文件,在文件之间间隔1ms。这有助于防止浏览器在加载过程中被完全锁定,但浏览器仍会因加载数据而陷入困境。我正在加载的每个文件如下所示:Javascript 将大量数据加载到内存-最有效的方法?,javascript,jquery,data-structures,Javascript,Jquery,Data Structures,我有一个基于网络的文档搜索/查看系统,我正在为客户开发。该系统的一部分是一个搜索系统,允许客户端搜索文档中包含的术语。我已经创建了必要的搜索数据文件,但是有很多数据需要加载,加载所有数据需要8-20秒。根据需要搜索的文档,数据被分为40-100个文件。每个文件的大小在40-350kb之间 此外,此应用程序必须能够在本地文件系统上运行,以及通过Web服务器运行 当网页加载时,我可以生成需要加载的搜索数据文件列表。必须先加载整个列表,才能将网页视为可用 有了序言,让我们看看我现在是怎么做的 在知道整
AddToBookData(0,[0,1,2,3,4,5,6,7,8]);
AddToBookData(1,[0,1,2,3,4,5,6,7,8]);
AddToBookData(2,[0,1,2,3,4,5,6,7,8]);
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
}
function AddToBookData(json) {
BookData[BookIndex].push([json.key,json.values]);
}
[
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 2,
"values" : [0,1,2,3,4,5,6,7,8]
}
]
{
"file1" : [
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
// all the rest...
],
"file2" : [
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
// yadda yadda
]
}
其中每一行都是一个函数调用,用于向数组中添加数据。“AddToBookData”函数仅执行以下操作:
function AddToBookData(index1,value1){
BookData[BookIndex].push([index1,value1]);
}
var test_array[..........(data structure I need).......]
BookData[BookIndex] = test_array;
这是现行的制度。加载所有数据后,“AddToBookData”可以被调用100000次以上
我认为这是非常低效的,因此我编写了一个脚本来获取包含上述所有函数调用的test.js文件,并对其进行处理以将其更改为一个巨大的数组,该数组与BookData正在创建的数据结构相同。我没有像旧系统那样进行所有函数调用,而是简单地执行以下操作:
function AddToBookData(index1,value1){
BookData[BookIndex].push([index1,value1]);
}
var test_array[..........(data structure I need).......]
BookData[BookIndex] = test_array;
我希望看到性能的提高,因为我删除了上面所有的函数调用,这个方法需要稍微多一些时间来创建精确的数据结构。我应该注意到,“test_数组”在我的真实测试中包含了略多于90000个元素
这两种加载数据的方法似乎具有大致相同的CPU利用率。我很惊讶地发现这一点,因为我希望第二种方法只需要很少的CPU时间,因为数据结构是事先创建的
请告知
< P>而不是使用<代码> $.GETScript < /C> >加载包含函数调用的JavaScript文件,请考虑使用。这可能会提高性能。这些文件现在看起来如下所示:AddToBookData(0,[0,1,2,3,4,5,6,7,8]);
AddToBookData(1,[0,1,2,3,4,5,6,7,8]);
AddToBookData(2,[0,1,2,3,4,5,6,7,8]);
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
}
function AddToBookData(json) {
BookData[BookIndex].push([json.key,json.values]);
}
[
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 2,
"values" : [0,1,2,3,4,5,6,7,8]
}
]
{
"file1" : [
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
// all the rest...
],
"file2" : [
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
// yadda yadda
]
}
收到JSON响应后,您可以对其调用AddToBookData
,如下所示:
AddToBookData(0,[0,1,2,3,4,5,6,7,8]);
AddToBookData(1,[0,1,2,3,4,5,6,7,8]);
AddToBookData(2,[0,1,2,3,4,5,6,7,8]);
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
}
function AddToBookData(json) {
BookData[BookIndex].push([json.key,json.values]);
}
[
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 2,
"values" : [0,1,2,3,4,5,6,7,8]
}
]
{
"file1" : [
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
// all the rest...
],
"file2" : [
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
// yadda yadda
]
}
如果您的文件有多组对AddToBookData的调用,则可以按如下方式对其进行结构:
AddToBookData(0,[0,1,2,3,4,5,6,7,8]);
AddToBookData(1,[0,1,2,3,4,5,6,7,8]);
AddToBookData(2,[0,1,2,3,4,5,6,7,8]);
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
}
function AddToBookData(json) {
BookData[BookIndex].push([json.key,json.values]);
}
[
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 2,
"values" : [0,1,2,3,4,5,6,7,8]
}
]
{
"file1" : [
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
// all the rest...
],
"file2" : [
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
// yadda yadda
]
}
然后更改AddToBookData
函数以补偿新结构:
function AddToBookData(json) {
$.each(json, function(index, data) {
BookData[BookIndex].push([data.key,data.values]);
});
}
附录我怀疑,无论使用何种方法将数据从文件传输到
BookData
数组,真正的瓶颈在于请求的数量。这些文件必须分成40-100个片段吗?如果更改为JSON格式,则可以加载如下所示的单个文件:
AddToBookData(0,[0,1,2,3,4,5,6,7,8]);
AddToBookData(1,[0,1,2,3,4,5,6,7,8]);
AddToBookData(2,[0,1,2,3,4,5,6,7,8]);
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
}
function AddToBookData(json) {
BookData[BookIndex].push([json.key,json.values]);
}
[
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
{
"key" : 2,
"values" : [0,1,2,3,4,5,6,7,8]
}
]
{
"file1" : [
{
"key" : 0,
"values" : [0,1,2,3,4,5,6,7,8]
},
// all the rest...
],
"file2" : [
{
"key" : 1,
"values" : [0,1,2,3,4,5,6,7,8]
},
// yadda yadda
]
}
然后你可以做一个请求,加载所有你需要的数据,然后继续。。。虽然浏览器最初可能会锁定(虽然,可能不会),但这样做可能会更快
如果您不熟悉,这里有一个不错的JSON教程:我测试了三种方法,将相同的9000000点数据集加载到Firefox 3.64中
1: Stephen's GetJSON Method
2) My function based push method
3) My pre-processed array appending method:
我以两种方式运行测试:在测试的第一次迭代中,我导入了100个文件,其中包含10000行数据,每行包含9个数据元素[0,1,2,3,4,5,6,7,8]
第二次交互时,我尝试合并文件,因此我导入了一个包含900万个数据点的文件
这比我将要使用的数据集要大得多,但它有助于演示各种导入方法的速度
Separate files: Combined file:
JSON: 34 seconds 34
FUNC-BASED: 17.5 24
ARRAY-BASED: 23 46
至少可以说,结果很有趣。加载每个网页后,我关闭了浏览器,并分别运行了4次测试,以最小化网络流量/变化的影响。(通过网络运行,使用文件服务器)。您看到的数字是平均值,尽管单个运行之间的差异最多只有一秒或两秒。看起来有两个基本的优化数据加载区域,可以单独考虑和处理:
对于没有工作者的浏览器,您可以考虑稍微增加<代码> SETTIMEOUT间隔,以提供浏览器时间来服务用户以及您的JS。这将使事情实际上稍微慢一点,但当与下一点结合时,可能会增加用户的幸福感
提供进度反馈 Fo