问题:我试图通过使用多个Web工作人员来加速我的IndexedDB搜索,因此同时执行多个读取事务,但它并没有真正起作用,而我的CPU只能达到30-35左右利用率%。我有一个4核处理器,希望产生4个网络工作者会大大缩短搜索时间。
我正在使用带有WebExtension的Firefox 53;其他浏览器不是一种选择。
DATABASE:我有一个包含大约250,000条记录的数据存储,每条记录包含大约30个密钥,其中一些包含文本段落。
任务:对给定密钥执行字符串搜索以查找匹配值。目前,在单个线程上花费大约90秒。添加额外的工作人员会将时间缩短到大约75秒。比这更多的工人没有明显的效果。对我来说可接受的时间不到10秒(有点类似于SQL数据库)。
CURRENT STRATEGY:为每个处理器生成一个worker,并创建一个在worker发送消息时解析的Promise。在每个工作人员中,打开数据库,均匀地划分记录,然后搜索字符串。如果你是第一个工人,那么我会通过第一个记录开始,第二个记录的第二个记录等等。然后按工人数量提前。所以第一个工人检查记录1,5,9等。第二个工人检查2,6,10等。当然,我也可以让第一个工人检查1-50,第二个工人检查51-100等等(但显然每个都有数千个。)
在单个线程上使用getAll()
花费了几乎两倍的时间和4GB的内存。将其分成4个范围可以在合并结果后将时间缩短到总共大约40秒(每次运行脚本时,40秒都会变化很大)。
关于如何使这项工作的任何想法,或其他显着加快搜索速度的建议?
background.js:
var key = whatever, val = something
var proc = navigator.hardwareConcurrency; // Number of processors
var wPromise = []; // Array of promises (one for each worker)
var workers = [];
/* Create a worker for each processor */
for (var pos = 0; pos < proc; pos++) {
workers[pos] = new Worker("js/dbQuery.js");
wPromise.push(
new Promise( resolve => workers[pos].onmessage = resolve )
);
workers[pos].postMessage({key:key, val:val, pos:pos, proc:proc});
}
return Promise.all(wPromise); // Do something once all the workers have finished
dbQuery.js:
onmessage = e => {
var data = e.data;
var req = indexedDB.open("Blah", 1);
req.onsuccess = e => {
var keyArr = [];
var db = e.currentTarget.result;
db.transaction("Blah").objectStore("Blah").index(data.key).openKeyCursor().onsuccess = e => {
var cursor = e.target.result;
if (cursor) {
if (data.pos) {
cursor.advance(data.pos); // Start searching at a position based on which web worker
data.pos = false;
}
else {
if (cursor.key.includes(data.val)) {
keyArr.push(cursor.primaryKey); // Store key if value is a match
}
cursor.advance(data.proc); // Advance position based on number of processors
}
}
else {
db.close();
postMessage(keyArr);
close();
}
}
}
}
答案 0 :(得分:0)
关于如何使这项工作或其他建议的任何想法 显着加快搜索速度?
您可以使用Promise.race()
替换Promise.all()
,以便在找到匹配项后返回已解决的Promise
,而不是等待传递给{{Promise
的所有Promise.all()
1}}待解决。