如何在javascript中将文件读入内存时计算好的批量大小?

时间:2017-12-19 03:12:30

标签: javascript performance memory filereader

在javascript中,我想阅读所有选定的用户文件。

我使用文件夹选择输入字段来获取文件,从导航器变量中获取可用内核的数量,甚至是gb中的RAM。

我正在使用队列算法,因此我根据可用核心创建了一个Web worker任务。

然后我遍历每个工作人员,并从文件列表中切掉batch大小,然后交给工人。

每次工作人员完成时,它会从文件列表中获取另一个大小为batch的片段,直到没有剩余文件,并且所有工作者都已完成。

我无法确定要使用的batch大小值。它可以修复或基于某些公式。

我发现如果我有77个文件,批量大小为16可以正常工作,如果我有151324,那么批量大小为300就可以了。但我不想选择一个可以扼杀记忆的批量大小,但同时也要加快速度。

我也从每个文件中读取最多75千字节。

此外,每个文件都有一个size属性。如果我做任何预先分类,它会有所作为吗?

有谁知道怎么做?

由于

1 个答案:

答案 0 :(得分:0)

必须对此进行测试,但是通过使用URL#createObjectURL,您理论上可以创建指向磁盘上文件的直接指针,可供您的工作人员使用,而无需从主线程复制任何数据。

这意味着您的批量大小可能只是files.length / numberOfWorkers

<强> A rough proof of concept:
(作为一个小提琴,因为StackSnippet的null起源iframe使这个技巧变得不可能......)

在工人中:

self.onmessage = e => {
  Promise.all(
    e.data.map(async (url)=> 
      fetch(url).then(r=>r.blob())
    // here you can do whatever you have to do with the file
      .then(file => new FileReaderSync()
      .readAsText(file.slice(0,75))
       )
    )
  )
  .then(console.log)
  .catch(console.error);
};
</script>

在主页面中:

// workers is an Array containing your WebWorkers
inp.onchange = e => {
  const urls = [...inp.files]
    .map(file => URL.createObjectURL(file));
  const batchSize = Math.ceil(urls.length / (navigator.hardwareConcurrency));
  workers.forEach((worker, i) => {
    worker.postMessage(urls.slice(i*batchSize, i*batchSize + batchSize));  
  });
};