javascript - 使用多个 Worker 加速 IndexedDB 搜索

标签 javascript multithreading performance indexeddb web-worker

问题:我试图通过使用多个 Web Worker 来加快 IndexedDB 搜索速度,从而同时执行多个读取事务,但它并没有真正起作用,而且我的 CPU 只能达到 30-35 左右%利用率。我有一个 4 核处理器,希望生成 4 个 Web Worker 能够显着减少搜索时间。

我正在使用带有 WebExtension 的 Firefox 53;其他浏览器不是一个选项。

数据库:我有一个包含大约 250,000 条记录的数据存储,每个记录大约有 30 个键,其中一些包含文本段落。

任务:对给定键执行字符串搜索以查找匹配值。目前,在单个线程上完成此操作大约需要 90 秒。添加额外的工作人员可将该时间缩短至约 75 秒。更多的 worker 没有明显的影响。对我来说可接受的时间是 10 秒以下(有点类似于 SQL 数据库)。

当前策略:为每个处理器生成一个工作程序,并创建一个在工作程序发送消息时解析的 Promise。在每个worker中,打开数据库,将记录均匀划分,然后搜索字符串。如果您是第一个 worker ,则从第一条记录开始,如果您是第二个 worker ,则从第二条记录开始,依此类推。然后按 worker 数量前进。因此,第一个工作人员检查记录 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();
            }
        }
    }
}

最佳答案

Any ideas on how I can make this work, or other suggestions for significantly speeding up the search?

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

关于javascript - 使用多个 Worker 加速 IndexedDB 搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44349168/

相关文章:

python - 如何停止 Python 线程中的 for 循环?

mongodb - 是否可以提高 Mongoexport 的速度?

javascript - 如何在 TypeScript 中向 addEventListener 添加被动选项?

javascript - xo Lint 错误 : `document` is not defined

javascript - 虚假? && 运算符如何使 0 返回 0 而不是 NaN?

java - 如何在java中的超时值后停止/杀死多个线程

javascript - 在 Javascript 中压缩稀疏数组?

java - 线程中的Android无限循环

javascript - 直接在 JS 中动态改变 transition 还是使用 css classes 对性能更好?

c++ - 极快is_iequal? (不区分大小写的相等比较)