加速使用多个工作者进行IndexedDB搜索

时间:2017-06-03 22:41:34

标签: javascript multithreading performance indexeddb web-worker

问题:我试图通过使用多个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();
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

  

关于如何使这项工作或其他建议的任何想法   显着加快搜索速度?

您可以使用Promise.race()替换Promise.all(),以便在找到匹配项后返回已解决的Promise,而不是等待传递给{{Promise的所有Promise.all() 1}}待解决。