Node.jsマルチプロセスCPU密集タスクの実現
Node.jsシングルスレッドとマルチプロセス
Node.jsの性能が高いことはよく知られています。非同期イベントで駆動され、ブロックI/Oではなく、広く使われています。しかし、欠点もはっきりしています。Node.jsはシングルスレッドプログラムなので、長時間演算すると、CPUが即時にリリースできなくなります。したがって、CPU密集型アプリケーションには適していません。
もちろん、この問題を解決する方法がないわけではない。Node.jsはマルチスレッドをサポートしていませんが、マルチプルプロセスを作成してタスクを実行することができます。
Node.jsはchild_を提供しました。processとclusterの二つのモジュールは、複数のサブプロセスを作成するために使用できます。
次に、それぞれのスレッドとプロセスを使って、大量のフィボナッチ数をシミュレーションしてCPU密集試験を行います。
以下のコードは500回の位置を検索して35のフィボナッチ数です。(テストに便利です。時間を決めました。あまり長くも短くもない場所が必要です。)
単スレッド処理
コード:single.js
私のパソコンに表示された結果は44611 msです。
…
process:500/500
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
タスク完了時:44611 ms
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
500回の検索は44秒かかります。遅すぎます。位置がもっと大きいなら、数量がもっと多いと思いますが…
じゃ、私達はマルチプロセスを試してみます。⬇️
プロセス
clusterモジュールを採用して、Master-Workerモードでテストします。
全部で3つのjsです。それぞれメインスレッドコード:mater.js、サブプロセスコード:worker.js、入口コード:cluster.js(入口は単独でjsを書く必要がありません。ここでは、より明確に見えるようにします。)
メインスレッドコード:master.js
2.メインスレッドとサブプロセスとの間の通信は、send方式でデータを送信し、MEssageイベントを傍受してデータを受信することである。
3.私がES 6を使ったジェネナートジェネレータを使って、検索するたびにフィボナッチの数の位置をシミュレーションして生成しているかどうかは分かりません。😂,上記のスレッドと統一を保証するため)。このようにするのはすべての任務を一度に投げ出さないためで、たとえ投げてもふさがれることができますとしても、まだ手順の端に置くほうがいいです。
サブプロセスコード:worker.js
私のパソコンで結果を表示します。10724 msです。
process:500/500
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
タスク完了時:10724 ms
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
結果
上記の2つの方式に比べて,多プロセス処理速度は単スレッド処理速度の4倍以上であることが明らかになった。また、条件がある場合、CPUが十分であれば、プロセス数がもっと多くなり、速度も速くなります。
もっといい案や他の言語が必要とされるならもっといいです。Node.jsは生まれつきCPU密集型の応用に適しないです。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。
Node.jsの性能が高いことはよく知られています。非同期イベントで駆動され、ブロックI/Oではなく、広く使われています。しかし、欠点もはっきりしています。Node.jsはシングルスレッドプログラムなので、長時間演算すると、CPUが即時にリリースできなくなります。したがって、CPU密集型アプリケーションには適していません。
もちろん、この問題を解決する方法がないわけではない。Node.jsはマルチスレッドをサポートしていませんが、マルチプルプロセスを作成してタスクを実行することができます。
Node.jsはchild_を提供しました。processとclusterの二つのモジュールは、複数のサブプロセスを作成するために使用できます。
次に、それぞれのスレッドとプロセスを使って、大量のフィボナッチ数をシミュレーションしてCPU密集試験を行います。
以下のコードは500回の位置を検索して35のフィボナッチ数です。(テストに便利です。時間を決めました。あまり長くも短くもない場所が必要です。)
単スレッド処理
コード:single.js
function fibonacci(n) {
if (n == 0 || n == 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
let startTime = Date.now();
let totalCount = 500;
let completedCount = 0;
let n = 35;
for (let i = 0; i < totalCount; i++) {
fibonacci(n);
completedCount++;
console.log(`process: ${completedCount}/${totalCount}`);
}
console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
console.info(` , : ${Date.now() - startTime}ms`);
console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
node single.jsを実行して結果を調べます。私のパソコンに表示された結果は44611 msです。
…
process:500/500
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
タスク完了時:44611 ms
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
500回の検索は44秒かかります。遅すぎます。位置がもっと大きいなら、数量がもっと多いと思いますが…
じゃ、私達はマルチプロセスを試してみます。⬇️
プロセス
clusterモジュールを採用して、Master-Workerモードでテストします。
全部で3つのjsです。それぞれメインスレッドコード:mater.js、サブプロセスコード:worker.js、入口コード:cluster.js(入口は単独でjsを書く必要がありません。ここでは、より明確に見えるようにします。)
メインスレッドコード:master.js
const cluster = require("cluster");
const numCPUs = require("os").cpus().length;
//
cluster.setupMaster({
exec: "./worker.js",
slient: true
});
function run() {
//
const startTime = Date.now();
//
const totalCount = 500;
//
let completedCount = 0;
//
const fbGenerator = FbGenerator(totalCount);
if (cluster.isMaster) {
cluster.on("fork", function(worker) {
console.log(`[master] : fork worker ${worker.id}`);
});
cluster.on("exit", function(worker, code, signal) {
console.log(`[master] : worker ${worker.id} died`);
});
for (let i = 0; i < numCPUs; i++) {
const worker = cluster.fork();
//
worker.on("message", function(msg) {
// ,
completedCount++;
console.log(`process: ${completedCount}/${totalCount}`);
nextTask(this);
});
nextTask(worker);
}
} else {
process.on("message", function(msg) {
console.log(msg);
});
}
/**
*
*
* @param {ChildProcess} worker ,
*/
function nextTask(worker) {
//
const data = fbGenerator.next();
// , ,
if (data.done) {
done();
return;
}
//
//
worker.send(data.value);
}
/**
* ,
*/
function done() {
if (completedCount >= totalCount) {
cluster.disconnect();
console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
console.info(` , : ${Date.now() - startTime}ms`);
console.log("👏 👏 👏 👏 👏 👏 👏 👏 👏 👏");
}
}
}
/**
*
*/
function* FbGenerator(count) {
var n = 35;
for (var i = 0; i < count; i++) {
yield n;
}
return;
}
module.exports = {
run
};
1.ここでは、現在のコンピュータの論理CPUコアの数によって、サブプロセスを作成します。コンピュータの数によって違います。私のCPUは6つの物理コアです。超スレッド処理をサポートしていますので、論理コアの数は12です。だから、12個のサブプロセスを作成します。2.メインスレッドとサブプロセスとの間の通信は、send方式でデータを送信し、MEssageイベントを傍受してデータを受信することである。
3.私がES 6を使ったジェネナートジェネレータを使って、検索するたびにフィボナッチの数の位置をシミュレーションして生成しているかどうかは分かりません。😂,上記のスレッドと統一を保証するため)。このようにするのはすべての任務を一度に投げ出さないためで、たとえ投げてもふさがれることができますとしても、まだ手順の端に置くほうがいいです。
サブプロセスコード:worker.js
function fibonacci(n) {
if (n == 0 || n == 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
// ,
process.on("message", n => {
var res = fibonacci(n);
// ,
process.send(res);
});
:cluster.js
// js, run
const master = require("./master");
master.run();
node cluster.jsを実行して結果を調べます。私のパソコンで結果を表示します。10724 msです。
process:500/500
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
タスク完了時:10724 ms
👏 👏 👏 👏 👏 👏 👏 👏 👏 👏
結果
上記の2つの方式に比べて,多プロセス処理速度は単スレッド処理速度の4倍以上であることが明らかになった。また、条件がある場合、CPUが十分であれば、プロセス数がもっと多くなり、速度も速くなります。
もっといい案や他の言語が必要とされるならもっといいです。Node.jsは生まれつきCPU密集型の応用に適しないです。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。