在javascript中,我想读取所有选定的用户文件。
我使用文件夹选择输入字段来获取文件,从导航器变量中获取可用内核的数量,甚至是gb中的RAM。
我正在使用队列算法,所以我为每个可用核心创建一个Web worker任务。
然后我循环遍历每个工人,并从文件列表中切掉batch
大小,然后交给工人。
每次工作完成时,它会从文件列表中获取另一个大小为batch
的片段,直到没有剩余文件,并且所有工作者都已完成。
我无法弄清楚什么是一个好的batch
尺寸值使用。它可以是固定的或基于一些公式。
我发现,如果我有77个文件,批量大小为16可以正常工作,如果我有151324,那么批量大小为300就可以了。但我不想选择一个可以杀死内存的批量大小,但同时也要加快速度。
我还从每个文件中读取最多75千字节。
此外,每个文件都有一个size属性。如果我做任何预先分类,它会有所作为吗?
有谁知道如何做到这一点?
谢谢
这必须进行测试,但是通过使用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));
});
};