なぜ Node.js は完全なシングルスレッドではないと言えるのでしょうか?どのように理解すればよいでしょうか?次の記事でそれについて説明しますので、お役に立てれば幸いです。
node はイベント ループを使用して複数の同時実行を実現するシングルスレッド プログラムであることは誰もが知っていると思います。残念ながら、これは完全に正しいわけではありません。
では、なぜ Node.js は完全なシングルスレッド プログラムではないのでしょうか?
自分たちで作成したすべての Javascript、V8、およびイベント ループは、メインとなる同じスレッドで実行されます。スレッド。
おい、これはノードがシングルスレッドであることを意味するのではないか?
しかし、おそらく、そのノードには C コードを含む多くのモジュールがあることをご存じないかもしれません。
ノードはスレッドを制御する権限をユーザーに公開しませんが、C はマルチスレッドを使用できます。
それでは、ノードはいつマルチスレッドを使用するのでしょうか?
ノード メソッドが C の synchronous メソッドをバックグラウンドで呼び出す場合、そのメソッドはすべてメイン スレッドで実行されます。
ノード メソッドが C の asynchronous メソッドをバックグラウンドで呼び出すと、メイン スレッドで実行されないことがあります。
話は簡単です。コードを見せてください。
Herecrypto
関連モジュールの多くは C で書かれています。以下のプログラムは、パスワードを保存するために一般的に使用されるハッシュを計算する関数です。
import { pbkdf2Sync } from "crypto"; const startTime = Date.now(); let index = 0; for (index = 0; index < 3; index++) { pbkdf2Sync("secret", "salt", 100000, 64, "sha512"); const endTime = Date.now(); console.log(`${index} time, ${endTime - startTime}`); } const endTime = Date.now(); console.log(`in the end`);
出力時間、
0 time, 44 1 time, 90 2 time, 134 in the end
毎回約 45 ミリ秒かかり、コードがメイン スレッドで順番に実行されることがわかります。
最終出力が誰になるかに注目してください。 私の CPU では、ここでのハッシュに最大 45 ミリ秒かかることに注意してください。
import { cpus } from "os"; import { pbkdf2 } from "crypto"; console.log(cpus().length); let startTime = console.time("time-main-end"); for (let index = 0; index < 4; index++) { startTime = console.time(`time-${index}`); pbkdf2("secret", `salt${index}`, 100000, 64, "sha512", (err, derivedKey) => { if (err) throw err; console.timeEnd(`time-${index}`); }); } console.timeEnd("time-main-end");
出力時間
time-main-end: 0.31ms time-2: 45.646ms time-0: 46.055ms time-3: 46.846ms time-1: 47.159ms
ここでわかるように、メインスレッドが早い ただし、最終的に各計算にかかる時間は 45ms です。CPU がハッシュを計算するのにかかる時間は 45ms であることを知っておく必要があります。ここのノードは間違いなくハッシュ計算に複数のスレッドを使用します。
ここで呼び出し回数を10回に変更すると時間は以下のようになり、CPUコア数を使い切るにつれて時間も増加していることがわかります。もう一度、ノードがハッシュ計算に複数のスレッドを確実に使用していることが証明されました。
time-main-end: 0.451ms time-1: 44.977ms time-2: 46.069ms time-3: 50.033ms time-0: 51.381ms time-5: 96.429ms // 注意这里,从第五次时间开始增加了 time-7: 101.61ms time-4: 113.535ms time-6: 121.429ms time-9: 151.035ms time-8: 152.585ms
ここでは、ノードでマルチスレッドが確実に有効になっていることが証明されています。しかし、少し問題がありますか?私のコンピューターの CPU は AMD R5-5600U で、6 コアと 12 スレッドがあります。しかし、5 回目から時間が増加するのはなぜですか? ノードが CPU を十分に活用していないのでしょうか? ######理由は何ですか?
ノードは事前定義されたスレッド プールを使用します。このスレッド プールのデフォルト サイズは 4 です。
export UV_THREADPOOL_SIZE=6見てみましょう例:HTTP リクエスト
import { request } from "https"; const options = { hostname: "www.baidu.com", port: 443, path: "/img/PC_7ac6a6d319ba4ae29b38e5e4280e9122.png", method: "GET", }; let startTime = console.time(`main`); for (let index = 0; index < 15; index++) { startTime = console.time(`time-${index}`); const req = request(options, (res) => { console.log(`statusCode: ${res.statusCode}`); console.timeEnd(`time-${index}`); res.on("data", (d) => { // process.stdout.write(d); }); }); req.on("error", (error) => { console.error(error); }); req.end(); } console.timeEnd("main");
main: 13.927ms time-2: 83.247ms time-4: 89.641ms time-3: 91.497ms time-12: 91.661ms time-5: 94.677ms ..... time-8: 134.026ms time-1: 143.906ms time-13: 140.914ms time-10: 144.088ms
ノードの背後にある C の
asynchronousメソッドが最初にカーネル非同期サポートがあるかどうかを確認しようとする場合、たとえば、ここではネットワークに epoll (Linux) を使用してください。非同期メソッドを提供しない場合、ノードは独自のスレッド プールを使用します。 。
したがって、http リクエストは非同期ですが、カーネルによって実装されており、カーネルが完了すると C に通知され、C はコールバックを処理するようにメインスレッドに通知します。 それでは、Node のどの非同期メソッドがスレッド プールを使用するのでしょうか?どれがそうではないでしょうか?
ネイティブ カーナル非同期
非同期
が発生した場合、メソッドの裏側は C で書かれています。カーネル非同期サポートがある場合は、メインスレッドからメソッドに渡されます。処理用のカーネル。非同期の場合
メソッドの裏側は C で書かれています。カーネル非同期サポートがない場合は、メインスレッドからメソッドに渡されます。スレッドプール。スレッド プールとカーネルは結果をイベント ループに返します。JavaScript コールバックが登録されている場合は、処理のために V8 に渡されます。
そして、処理するものがなくなるまでこのようにループします。
つまり、Node は完全にシングルスレッド プログラムではありません。
ノード関連の知識の詳細については、nodejs チュートリアル を参照してください。
以上がNode.js が完全なシングルスレッド プログラムではないことを理解する方法 (簡単な分析)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。