将大量数据加载到内存中 - 最有效的方法吗?

use*_*099 20 javascript jquery data-structures

我有一个基于Web的文档搜索/查看系统,我正在为客户开发.该系统的一部分是一个搜索系统,允许客户端搜索文档中包含的术语[s].我已经创建了必要的搜索数据文件,但是需要加载大量数据,加载所有数据需要8-20秒.数据分为40-100个文件,具体取决于需要搜索的文档.每个文件都在40-350kb之间.

此外,此应用程序必须能够在本地文件系统上运行,也可以通过Web服务器运行.

当网页加载时,我可以生成我需要加载的搜索数据文件的列表.必须先加载整个列表,然后才能认为网页正常运行.

有了这个序言,让我们来看看我现在是怎么做的.

在我知道整个网页已加载后,我调用了一个loadData()函数

function loadData(){
            var d = new Date();
            var curr_min = d.getMinutes();
            var curr_sec = d.getSeconds();
         var curr_mil = d.getMilliseconds();
         console.log("test.js started background loading, time is: " + curr_min + ":" + curr_sec+ ":" + curr_mil);
          recursiveCall();
      }


   function recursiveCall(){
      if(file_array.length > 0){
         var string = file_array.pop();
         setTimeout(function(){$.getScript(string,recursiveCall);},1);
    }
    else{
        var d = new Date();
        var curr_min = d.getMinutes();
        var curr_sec = d.getSeconds();
        var curr_mil = d.getMilliseconds();
        console.log("test.js stopped background loading, time is: " + curr_min + ":" + curr_sec+ ":" + curr_mil);
    }
  }
Run Code Online (Sandbox Code Playgroud)

这样做是按顺序处理文件数组,文件之间间隔1ms.这有助于防止浏览器在加载过程中被完全锁定,但浏览器仍然会因加载数据而陷入困境.我正在加载的每个文件都是这样的:

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]);
Run Code Online (Sandbox Code Playgroud)

其中每一行都是一个将数据添加到数组的函数调用."AddToBookData"函数只执行以下操作:

    function AddToBookData(index1,value1){
         BookData[BookIndex].push([index1,value1]);
    }
Run Code Online (Sandbox Code Playgroud)

这是现有系统.加载所有数据后,"AddToBookData"可以被调用100,000次以上.

我认为这是非常低效的,所以我编写了一个脚本来获取包含上面所有函数调用的test.js文件,并对其进行处理以将其更改为一个巨大的数组,该数组等于BookData正在创建的数据结构.我没有进行旧系统所做的所有函数调用,而只是执行以下操作:

var test_array[..........(data structure I need).......]
BookData[BookIndex] = test_array;
Run Code Online (Sandbox Code Playgroud)

我期望看到性能提高,因为我正在删除上面的所有函数调用,此方法需要稍多的时间来创建确切的数据结构.我应该注意到"test_array"在我的真实世界测试中拥有略多于90,000个元素.

似乎两种加载数据的方法都具有大致相同的CPU利用率.我很惊讶地发现这一点,因为我希望第二种方法需要很少的CPU时间,因为数据结构是在手工创建的.

请指教?

Day*_*Day 15

看起来优化数据加载有两个基本区域,可以单独考虑和解决:

  1. 从服务器下载数据.您应该从多个较小文件的并行加载中获得胜利,而不是一个大文件.尝试同时加载的数量,牢记浏览器限制和太多并行连接的收益递减.请参阅我在jsfiddle上的并行顺序实验,但请记住,由于从github中提取测试数据的变幻莫测,结果会有所不同 - 您最好在更严格控制的情况下使用自己的数据进行测试.
  2. 尽可能高效地构建数据结构.你的结果看起来像一个多维数组,这篇关于JavaScript数组性能的有趣文章可能会给你一些关于这方面实验的想法.

但我不确定你能够在多大程度上优化单独的数据加载.要解决您的应用程序的实际问题(浏览器锁定时间过长)您是否考虑过诸如?

使用Web Workers

所有目标浏览器可能都不支持Web Workers,但应防止主浏览器线程在处理数据时锁定.

对于没有工作者的浏览器,您可以考虑setTimeout稍微增加间隔,以便为浏览器提供服务用户和JS的时间.这将使事情实际上稍微慢一点,但与下一点结合使用可能会增加用户的快乐.

提供进展反馈

对于具有工作能力和缺少工作人员的浏览器,请花一些时间使用进度条更新DOM.你知道有多少文件要加载,所以进度应该相当一致,虽然事情实际上可能稍微慢一点,如果用户得到反馈并且不认为浏览器已经锁定它们,用户会感觉更好.

延迟加载

正如jira在他的评论中所建议的那样.如果Google Instant可以在我们输入时搜索整个网络,是否真的无法让服务器返回包含当前图书中所有搜索关键字位置的文件?这个文件应该比书中所有单词的位置小得多,加载速度要快得多,这就是我假设你正在尝试尽可能快地加载?


use*_*099 5

我测试了三种将相同的 9,000,000 点数据集加载到 Firefox 3.64 的方法。

1: Stephen's GetJSON Method
2) My function based push method
3) My pre-processed array appending method:
Run Code Online (Sandbox Code Playgroud)

我以两种方式运行我的测试:第一次测试我导入了 100 个包含 10,000 行数据的文件,每行包含 9 个数据元素 [0,1,2,3,4,5,6,7,8]

在第二次交互中,我尝试合并文件,因此我导入了 1 个包含 900 万个数据点的文件。

这比我将使用的数据集大得多,但它有助于展示各种导入方法的速度。

Separate files:                 Combined file:

JSON:        34 seconds         34
FUNC-BASED:  17.5               24
ARRAY-BASED: 23                 46
Run Code Online (Sandbox Code Playgroud)

至少可以说,有趣的结果。我在加载每个网页后关闭了浏览器,并每次运行测试 4 次,以尽量减少网络流量/变化的影响。(通过网络运行,使用文件服务器)。您看到的数字是平均值,尽管单个运行最多只有一两秒的差异。