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

标签 javascript arrays node.js parallel-processing

我有一个像这样的 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",

}];

我需要根据 upvotesnumberOfCommentsshares 计算值 score,然后将其推回到 JSON 字典中,以便数组中的每个对象如下所示 -

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

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

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

P.S 我正在对此进行编码,假设数组中的元素将来可能会增长到 300-400 个元素。

最佳答案

下面----下的原始答案写于2015年,当时是正确的。从那时起,Node.js 获得了 worker threads 。但它们只能与SharedArrayBuffer字面上共享内存。 ,并且您不能将对象存储在 SharedArrayBuffer 中(某些序列化形式除外),SharedArrayBuffer 只能与 typed arrays 一起使用。 ,使用数字元素。

您可以将一个数组从一个线程传输到另一个线程(发送线程失去对它的访问权限,接收线程获得访问权限),因此您可以启动 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);
}
<小时/>

原始答案:

how can I speed up the score computation process to access each element parallelly and thus reduce the time it takes to compute the score for every element in the array?

你不能(合理地)。 NodeJS 只运行一个线程。要获得多个执行线程,您必须生成一个子进程,这比仅在一个线程上执行要慢很多

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

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

关于javascript - 使用node.js并行操作数组的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31096309/

相关文章:

javascript - 在加载和 Ajax 加载的内容上运行 JS 代码

java - 需要 Java 数组帮助使用扫描器类输出平均和排序方法

javascript - 跳过 FOR 循环中的多个元素,Javascript

javascript - ReactJS 和 Node——错误 400 错误请求

javascript - 从可拖动标记前往新街道和城镇

javascript - 是否可以在 D3.js 中使用日期范围作为时间刻度上的单独日期项目?

arrays - 是否可以在不循环的情况下对 Matlab 中的结构子字段数组进行平均?

node.js - 当 req body json 太重时 ExpressJS CORS 错误

php - Nodejs从数据库读取 session

javascript - 根据现有对象数组的几个属性返回新的对象数组