1. ホーム
  2. ジャバスクリプト

[解決済み】Node.jsは内部でThreadsに依存しているのに、どうして本質的に高速なのですか?

2022-04-16 08:02:53

質問

以下の動画を見ました。 Node.jsの紹介 で、どうやってスピードの恩恵を受けるのか、まだ理解できていません。

主に、あるところでRyan Dahl(Node.jsの作者)が、Node.jsはスレッドベースではなくイベントループベースであると言っています。 スレッドは高価なので、活用するのは並行プログラミングの専門家に任せるべきだということです。

その後、Node.js のアーキテクチャスタックを示し、内部で独自のスレッドプールを持つ C の実装を基礎としていることを説明しました。 だから、明らかにNode.jsの開発者は、自分自身のスレッドをキックオフしたり、スレッドプールを直接使用したりはしない。 それだけは理解しています。

Node.jsはまだスレッドを使っているという点が理解できません。実装を隠しているだけで、50人が50個のファイル(現在メモリ上にない)をリクエストしたら、50個のスレッドが必要ではないのでしょうか?

唯一の違いは、内部で管理されているので、Node.js開発者はスレッド化された詳細をコーディングする必要がないことですが、その下ではまだIO(ブロック化)ファイル要求を処理するためにスレッドを使用しています。

つまり、1つの問題(スレッド)を取り上げて、その問題がまだ存在している間はそれを隠しているだけではないのでしょうか。

私がまだ理解していない詳細があるに違いない。

どのように解決するのですか?

実は、ここではいくつかの異なる事柄が混同されているのです。 しかし、これは「スレッドは本当に難しい」というミームから始まっています。 もしスレッドが難しいなら、スレッドを使うときに、1)バグで壊れたり、2)可能な限り効率的に使わなかったりする可能性が高くなるわけです。 (2)は、あなたが質問しているものです。

彼が挙げた例の一つを考えてみてください。リクエストが来て、何らかのクエリを実行し、その結果を使って何かをするというものです。 これを標準的な手続きで書くと、次のようなコードになります。

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

もしリクエストが来たことによって、上記のコードを実行する新しいスレッドを作成した場合、スレッドがそこに座っていて、何もしていない間に query() が実行されています。 (Ryanによれば、Apacheはオリジナルのリクエストを満たすためにシングルスレッドを使っているのに対し、nginxはそうではないため、彼の言うようなケースで凌駕しています)。

さて、もしあなたが本当に賢いのであれば、上記のコードを、クエリを実行している間に環境が消えて他のことができるような方法で表現することでしょう。

query( statement: "select smurfs from some_mushroom", callback: go_do_something_with_result() );

これは基本的にnode.jsがやっていることです。 基本的には、言語と環境の都合で、クロージャについて指摘したように、あなたのコードを装飾しているのです。 そういう意味では、node.jsは 新しい 非同期I/Oを発明したという意味では(誰もそんなことを主張しているわけではありませんが)、表現方法が少し違うという点では新しいと思います。

注:私が「環境はいつ何を実行するかについて賢い」と言ったとき、具体的には、あるI/Oを開始するのに使ったスレッドを、他のリクエストや、並行して行える計算を処理したり、他の並列I/Oを開始するのに使うことができる、という意味である。 (同じリクエストに対してより多くの作業を開始できるほどnodeが洗練されているかは定かではありませんが、イメージはつかめると思います)。