繁体   English   中英

使用 node.js 并行操作数组元素?

[英]Manipulating elements of an array in parallel using node.js?

我有一个像这样的 json 对象数组 -

var resultsArr = [
{
    "upvotes": "45",
    "postID": "4555",
    "numberOfComments": "45",
    "shares":"22"
},
{
    "upvotes": "21",
    "postID": "4665",
    "numberOfComments": "20",
    "shares":"24"
},
{
    "upvotes": "4",
    "postID": "77366",
    "numberOfComments": "0",
    "shares":"4"
},
{
    "upvotes": "49",
    "postID": "6565",
    "numberOfComments": "22",
    "shares":"54",

}];

我需要计算一个数值score基于upvotesnumberOfCommentsshares ,然后将其推回JSON字典,使得在阵列看起来像这样的每一个对象-

var resultsArr= [{
....
},
{
    "upvotes": "49",
    "postID": "6565",
    "numberOfComments": "22",
    "shares":"54",
    "score":"20"
}]

我可以使用for loop访问此数组中的 json 对象,但根据我的理解,它按顺序访问每个元素。

鉴于数组中将有大约 100-200 个项目,如何加快分数计算过程以并行访问每个元素,从而减少计算数组中每个元素的分数所需的时间?

PS 我正在编码这个,假设数组中的元素将来可能会增长到 300-400 个元素。

下面----下的原始答案是2015年写的,当时是真的。 从那时起,Node.js 获得了工作线程 但是它们只能与SharedArrayBuffer真正共享内存,并且您不能在SharedArrayBuffer存储对象(某些序列化形式除外), SharedArrayBuffer只能与使用数字元素的类型化数组一起使用。

您可以数组从一个线程传输到另一个线程(发送线程无法访问它,接收线程获得访问权限),因此您可以启动 N 个线程并将数组的一部分传输到每个线程。 他们将并行处理它,并将发布结果返回到主线程。

只是一个草图:

const { Worker } = require("worker_threads"); // If still using Node.js's CJS modules

function processChunkInWorker(script, chunk) {
    return new Promise((resolve, reject) => {
        const w = new Worker(script, {
            workerData: chunk
        });
        w.on("message", result => {
           resolve(result);
        });
    });
}
async function setScores(data, workerCount = 4) {
    const chunkSize = Math.round(data.length / workerCount);
    await Promise.all(
        Array.from({length: workerCount}, async (_, index) => {
            let chunkStart = index * chunkSize;
            const chunkEnd = index < workerCount - 1 ? (chunkStart + chunkSize) : data.length;
            const scores = await processChunkInWorker("./calcscore.js", data.slice(chunkStart, chunkEnd));
            for (const score of scores) {
                data[chunkStart++].score = score;
            }
        })
    );
}

(async () => {
    try {
        const data = /*...load the data...*/;
        await setScores(data);
        console.log(data);
    } catch (e) {
        console.error(e.message, e.stack);
    }
})();

其中calcscore.js类似于:

const { Worker, isMainThread, parentPort, workerData } = require("worker_threads"); // If still using Node.js's CJS modules
if (!isMainThread) {
    const scores = new Float64Array(workerData.map(({upvotes, numberOfComments, shares}) => +upvotes + +numberOfComments + +shares));
    parentPort.postMessage(scores, scores.buffer);
}

原答案

如何加快分数计算过程以并行访问每个元素,从而减少计算数组中每个元素的分数所需的时间?

你不能(合理地)。 NodeJS 只运行一个线程。 为了得到执行多个线程,你必须生成一个子进程,这将是慢了很多,不仅仅是做一个线程。

300-400 个元素不算什么(即使 3-4百万也算不了什么;3M 在我的机器上大约需要 289 毫秒,4M 需要 384 毫秒)。 没有必要把事情复杂化。 只是:

resultsArr.forEach(function(entry) {
    // update `entry` here
});

我通常使用这段代码

    loopWithPromises = async (array, callback) => Promise.all(array.map(callback))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM