node.jsでの並行タスクにはどちらが適していますか?繊維?ウェブワーカー?またはスレッド?


111

私はいつかnode.jsに出会いましたが、とても気に入りました。しかし、すぐに、CPUを集中的に使用するタスクを実行する機能が大幅に不足していることがわかりました。そこで、グーグルを開始し、問題を解決するために次の回答を得ました。ファイバー、ウェブワーカー、スレッド(thread-a-gogo)。どちらを使用するかは混乱であり、そのうちの1つは間違いなく使用する必要があります。結局のところ、IOだけが得意で他には何もないサーバーを用意する目的は何でしょうか。提案が必要です!

更新:

私は遅れている方法を考えていました。それ以上の提案が必要です。さて、私が考えたのはこれです:(thread_a_gogoまたは多分ウェブワーカーを使用して)いくつかのスレッドを作成しましょう。今、それらをさらに必要とする場合、さらに作成することができます。ただし、作成プロセスにはいくつかの制限があります。(システムによって暗示されるわけではありませんが、おそらくオーバーヘッドが原因です)。これで、制限を超えると、新しいノードをフォークして、そのノード上にスレッドを作成し始めることができます。この方法では、制限に達するまで続行できます(結局のところ、プロセスにも大きなオーバーヘッドがあります)。この制限に達すると、タスクのキューイングを開始します。スレッドが解放されるたびに、新しいタスクが割り当てられます。このように、それはスムーズに進むことができます。

それで私はそう思ったのです。このアイデアは良いですか?私はこのすべてのプロセスとスレッドに関するものは少し新しいので、専門知識はありません。ご意見をお聞かせください。

ありがとう。:)


注意:ワーカーはブラウザ仕様であり、JavaScript機能ではありません。
FredTheWebGuy 2013

そうですね。私の質問はnode.js-サーバーコードについてであり、クライアント側についてではありませんでした!
Parth Thakkar 2013

明確化-元の質問はNodeJのWebワーカーに関するものだったようですが、不可能です-NodeJは「スレッド」を使用しています。ただし、NodeJsランタイム内でWebWorker構文を許可するNodeJSモジュールが浮かんでいます。
FredTheWebGuy 2013

回答:


330

ノードには完全に異なるパラダイムがあり、それが正しくキャプチャされると、問題を解決するこの異なる方法を簡単に確認できます。同じことをする別の方法があるので、Node application(1)で複数のスレッドを必要とすることはありません。複数のプロセスを作成します。ただし、たとえば、Apache Web ServerのPrefork mpmが行う方法とは非常に異なります。

とりあえず、CPUコアは1つだけで、いくつかの作業を行うアプリケーションを(Nodeの方法で)開発するとします。私たちの仕事は、コンテンツをバイト単位で実行する大きなファイルを処理することです。私たちのソフトウェアの最良の方法は、ファイルの先頭から作業を開始し、バイト単位で最後まで作業を進めることです。

-ヘイ、ハサン、あなたは私の祖父の時代からの初心者か非常に古い学校のどちらかだと思います!!! いくつかのスレッドを作成して、それをはるかに高速にしてみませんか?

-ああ、CPUコアは1つしかありません。

- だから何?いくつかのスレッドの男を作成し、それをより速くします!

-そのようには機能しません。スレッドを作成すると、速度が遅くなります。スレッド間の切り替えのためにシステムに多くのオーバーヘッドを追加し、それらにわずかな時間を与えようとし、プロセス内でこれらのスレッド間の通信を試みます。これらすべての事実に加えて、並行して実行できる1つのジョブを複数の部分にどのように分割するかについても考えなければなりません。

-わかった、わかった、あなたは貧しい。私のコンピューターを使用してみましょう。32コアです!

-うわー、あなたは私の親愛なる友人、すごいです、ありがとうございました。それは有り難いです!

その後、仕事に戻ります。豊富な友人のおかげで、今では32個のCPUコアがあります。私たちが守らなければならないルールが変わりました。今、私たちは与えられたこのすべての富を利用したいと思います。

複数のコアを使用するには、並行して処理できる部分に作業を分割する方法を見つける必要があります。ノードでない場合は、これにスレッドを使用します。32スレッド、各CPUコアに1つ。ただし、Nodeがあるので、32のNodeプロセスを作成します。

スレッドは、Nodeプロセスの優れた代替手段になる可能性があり、おそらくより良い方法です。ただし、作業がすでに定義されており、その処理方法を完全に制御できる特定の種類のジョブでのみです。これ以外に、私たちが制御できない方法でジョブが外部から発生し、できるだけ迅速に応答したいという他のすべての種類の問題については、ノードの方法は間違いなく優れています。

-ヘイ、ハサン、まだシングルスレッドで作業していますか?どうしたの?私はあなたが望むものをあなたに提供したところです。言い訳はもうありません。スレッドを作成し、より高速に実行します。

-作業を細かく分割しましたが、すべてのプロセスがこれらの部分のいずれかで並行して動作します。

-なぜスレッドを作成しないのですか?

-申し訳ありませんが、使えないと思います。あなたが望むならあなたはあなたのコンピュータを取ることができますか?

-いいえ、大丈夫です。私はクールですが、なぜスレッドを使用しないのか理解できません。

-コンピューターありがとうございます。:)私はすでに作品を断片に分割し、これらの断片を並行して処理するプロセスを作成しています。すべてのCPUコアが完全に利用されます。プロセスの代わりにスレッドでこれを行うことができます。しかし、Nodeにはこの方法があり、上司のParth ThakkarがNodeを使用することを望んでいます。

-承知しました。別のコンピュータが必要かどうかをお知らせください。:p

32の代わりに33のプロセスを作成すると、オペレーティングシステムのスケジューラはスレッドを一時停止し、他のスレッドを開始し、いくつかのサイクルの後で一時停止し、他のスレッドを再起動します... いりません。実際には、32コアを搭載したシステムで、私も31をすることができ、正確に32のプロセスを作成したいとは思わないでしょう立派。このシステムで動作するのは私のアプリケーションだけではないからです。特に32の部屋がある場合は、他のことのために少し部屋を残すことは良いことです。

CPUを集中的に使用するタスクにプロセッサを完全に利用することについては、同じページにいると思います。

-うーん、ハサン、あなたを少しからかって申し訳ありません。私はあなたを今よりよく理解していると思います。しかし、まだ説明が必要なことがあります。何百ものスレッドを実行することについての話題は何ですか?私は、スレッドがforkプロセスよりもはるかに高速に作成および処理できないことをどこでも読んでいますか?スレッドの代わりにプロセスをフォークし、それがNodeで得られる最高のものだと思っています。では、Nodeはこの種の作業には適切ではないのでしょうか。

-心配いりません、私もかっこいいです。誰もがそういうことを言うので、聞き慣れていると思います。

- そう?ノードはこれに適していませんか?

-ノードはこれに完全に適していますが、スレッドも優れている場合があります。スレッド/プロセス作成のオーバーヘッドについては; あなたがたくさん繰り返すことについては、ミリ秒ごとに数えます。ただし、作成するプロセスは32のみであり、少し時間がかかります。それは一度だけ起こります。違いはありません。

-では、何千ものスレッドをいつ作成したいですか?

-何千ものスレッドを作成したくない。ただし、HTTPリクエストを処理するWebサーバーなど、外部からの作業を実行しているシステムでは、リクエストごとにスレッドを使用している場合は、多数のスレッドが作成されます。

-ノードは違いますか?正しい?

- はい、正確に。これがNodeが本当に輝く場所です。スレッドはプロセスよりもはるかに軽量であるように、関数呼び出しはスレッドよりもはるかに軽量です。ノードはスレッドを作成する代わりに関数を呼び出します。Webサーバーの例では、すべての着信要求が関数呼び出しを引き起こします。

-うーん、面白いです。ただし、複数のスレッドを使用していない場合は、同時に1つの関数しか実行できません。大量のリクエストが同時にWebサーバーに到着した場合、これはどのように機能しますか?

-関数の実行方法については、一度に1つずつ、2つを並行して実行することはできません。つまり、単一のプロセスでは、一度に実行されるコードのスコープは1つだけです。OSスケジューラは、プロセスを一時停止して別のプロセスに時間を与えるのではなく、この関数を一時停止して別の関数に切り替えません。プロセス内の別のスレッドではありません。(2)

-では、プロセスは一度に2つのリクエストをどのように処理できますか?

-システムに十分なリソース(RAM、ネットワークなど)がある限り、プロセスは一度に数万のリクエストを処理できます。これらの関数の実行方法は、主な違いです。

-うーん、今興奮する必要がありますか?

-多分:)ノードはキューでループを実行します。このキューには私たちの仕事、つまり着信リクエストの処理を開始した呼び出しがあります。ここで最も重要な点は、実行する関数を設計する方法です。リクエストの処理を開始して、ジョブが完了するまで呼び出し側を待機させるのではなく、許容できる量の作業を行った後、関数をすばやく終了します。別のコンポーネントが処理を実行して値を返すのを待つ必要があるポイントに到達したら、それを待つのではなく、残りの作業をキューに追加する関数を終了するだけです。

-複雑に聞こえますか?

-いいえ、私は複雑に聞こえるかもしれません。しかし、システム自体は非常にシンプルで、完全に理にかなっています。

これら2つの開発者間の対話の引用をやめ、これらの関数がどのように機能するかについての最後の簡単な例の後で私の答えを終えたいと思います。

このようにして、OSスケジューラが通常行うことを実行しています。ある時点で作業を一時停止し、他の関数呼び出し(マルチスレッド環境の他のスレッドなど)を再び実行するまで実行させます。これは、システム上のすべてのスレッドにただ時間を与えようとするOSスケジューラに作業を任せるよりもはるかに優れています。私たちは、OSスケジューラよりも優れていることを理解しており、停止する必要があるときに停止することが期待されています。

以下は、ファイルを開いて読み取り、データを処理する簡単な例です。

同期方法:

Open File
Repeat This:    
    Read Some
    Do the work

非同期の方法:

Open File and Do this when it is ready: // Our function returns
    Repeat this:
        Read Some and when it is ready: // Returns again
            Do some work

ご覧のとおり、この関数はシステムにファイルを開くように要求し、ファイルが開かれるのを待ちません。ファイルの準備が整った後、次のステップを提供することによってそれ自体を終了します。戻ると、Nodeはキューで他の関数呼び出しを実行します。すべての関数を実行した後、イベントループは次のターンに移動します...

要約すると、Nodeはマルチスレッド開発とはまったく異なるパラダイムを持っています。しかし、これは物事が不足しているという意味ではありません。同期ジョブ(処理の順序と方法を決定できる場所)では、マルチスレッド並列処理と同様に機能します。サーバーへのリクエストのような外部からのジョブの場合、それは単に優れています。


(1)C / C ++のような他の言語でライブラリを構築する場合を除き、その場合でも、ジョブを分割するためのスレッドは作成しません。この種の作業には、2つのスレッドがあり、1つはノードとの通信を継続し、もう1つは実際の作業を行います。

(2)実際、最初の脚注で述べたのと同じ理由で、すべてのNodeプロセスには複数のスレッドがあります。しかし、これは1000スレッドが同様の作業を行うようなものではありません。これらの追加スレッドは、IOイベントを受け入れたり、プロセス間メッセージングを処理したりするためのものです。

更新(コメントで良い質問への返信として)

@マーク、建設的な批判をありがとう。Nodeのパラダイムでは、キュー内の他のすべての呼び出しが次々に実行されるように設計されていない限り、処理に時間がかかりすぎる関数を使用してはなりません。計算量の多いタスクの場合、全体像を見ると、「スレッドまたはプロセスを使用する必要があるか」という問題ではないことがわかります。しかし、「これらのタスクをバランスのとれた方法でサブタスクに分割して、システム上で複数のCPUコアを使用して並行して実行できるようにするにはどうすればよいか」という疑問があります。8コアのシステムで400ビデオファイルを処理するとします。一度に1つのファイルを処理する場合は、同じファイルの異なる部分を処理するシステムが必要です。その場合、マルチスレッドのシングルプロセスシステムの構築がより簡単になり、さらに効率的になります。複数のプロセスを実行し、状態の共有/通信が必要な場合にそれらの間でメッセージを渡すことにより、Nodeを引き続き使用できます。前に述べたように、Nodeを使用したマルチプロセスアプローチは同様にここでのタスクの種類でマルチスレッドアプローチ。それ以上ではありません。繰り返しますが、以前に言ったように、Nodeが優れているのは、複数のソースからのシステムへの入力としてこれらのタスクを受け取ったときです。Node内の多くの接続を同時に維持することは、接続ごとのスレッドや接続ごとのプロセスに比べてはるかに軽いためです。システム。

setTimeout(...,0)通話に関しては; 時間がかかるタスクの実行中に休憩を取り、キュー内の呼び出しが処理を共有できるようにする必要がある場合があります。タスクをさまざまな方法で分割することで、これらを回避できます。ただし、これは実際にはハックではなく、イベントキューが機能する方法にすぎません。また、をprocess.nextTick使用setTimeoutすると、経過時間の計算とチェックが必要になるため、この目的に使用する方がはるかに優れprocess.nextTickています。 」


9
すごい!すごい!私はあなたがこの質問に答えた方法を愛しました!:)
Parth Thakkar

48
確かに:)この回答記事に反対票を投じている非常に意地悪な人々がいるとは本当に信じられません!質問者はそれを「くそっ!そして、本の著者はこれを見て彼のウェブサイトに書いてくれると言っています。しかし、天才はそれを否定します。意地悪でこっそりと反対票を投じるのではなく、明るい知的品質を共有してコメントしてみませんか?なぜ素敵なものがそんなにあなたを邪魔するのですか?本当に有益なことができる他の人々にリーチするのに役立つ何かを防止したいのはなぜですか?
hasanyasin 2012

9
これは完全に公正な答えではありません。関数呼び出しを「すぐに終了」できない、計算量の多いタスクについてはどうでしょうか。一部の人々setTimeout(...,0)はこれのためにいくつかのハックを使用していると思いますが、このシナリオで別のスレッドを使用することは確かに優れているでしょうか?
mpen 2013年

3
@hasanyasinこれは、私がこれまでに見つけたノードに関する最も素晴らしい説明です!:)
Venemo

7
@Mark一般に、計算コストが高い場合は、トレッド/プロセスワーカー用のオプション/モジュールがあります...一般に、これらのタイプの場合は、メッセージキューを使用し、タスクを処理するワーカープロセスをキューから時間を取り、そのタスクを実行します。これにより、複数のサーバーにスケーリングすることもできます。これらの線に沿って、Substackには、あなたが見ることができるプロビジョニングとスケーリングに向けられた多くのモジュールがあります。
Tracker1 2013年

34

(2016年更新:Webワーカーはio.jsに入ります。Node.jsフォーク Node.js v7-以下を参照してください。)

(2017年更新:WebワーカーはNode.js v7またはv8に移行しません -以下を参照してください。)

(2018年更新:Webワーカー Node.js Node v10.5.0に移行します-以下を参照してください。)

いくつかの説明

上記の回答を読んだところで、JavaScriptの一般的な哲学、特に同時実行性に関するノードの哲学に反するものはWebワーカーにはないことを指摘したいと思います。(もしあったとしても、それはWHATWGでさえ議論されず、ブラウザーでの実装ははるかに少ないでしょう)。

ウェブワーカーは、非同期でアクセスされる軽量のマイクロサービスと考えることができます。状態は共有されません。ロックの問題はありません。ブロッキングはありません。同期は必要ありません。NodeプログラムからRESTfulサービスを使用する場合と同様に、RESTfulサービスは独自のイベントループと同じスレッドにないため、「マルチスレッド」になったことを心配する必要はありません。これは、非同期にアクセスする別個のサービスであり、それが重要です。

Webワーカーについても同様です。完全に別個のコンテキストで実行されるコードと通信するための単なるAPIであり、厳密に非同期の非ブロッキングAPIのため、異なるスレッド、異なるプロセス、異なるcgroup、ゾーン、コンテナー、または異なるマシンであるかどうかは完全に無関係です。すべてのデータは値で渡されます。

実際のところ、Webワーカーは概念的にはNodeに最適です。多くの人が気づいていませんが、偶発的にスレッドを非常に多く使用し、実際には「コード以外はすべて並列で実行されます」-を参照してください。

しかし、Webワーカーはスレッドを使用して実装する必要さえありません。ウェブワーカーAPIが使用されている限り、クラウドでプロセス、グリーンスレッド、さらにはRESTfulサービスを使用できます。同時実行モデルの詳細が公開されないため、値渡しのセマンティクスを持つメッセージ受け渡しAPIの全体的な美しさは、基礎となる実装がほとんど無関係であることです。

シングルスレッドイベントループは、I / Oバウンド操作に最適です。これは、CPUにバインドされた操作、特に長時間実行される操作に対してはうまく機能しません。そのためには、より多くのプロセスを生成するか、スレッドを使用する必要があります。子プロセスとプロセス間通信をポータブルな方法で管理することは非常に難しく、単純なタスクではやり過ぎと見なされることがよくありますが、スレッドを使用することは、適切に行うことが非常に難しいロックと同期の問題に対処することを意味します。

頻繁に推奨されるのは、実行時間の長いCPUバウンド操作を小さなタスクに分割することです(setIntervalを高速化するため私の回答の「元の回答」セクションの例のようなもの)。 1つのCPUコアより。

Webワーカーはサーバーではなくブラウザー用に作成されたと基本的に言っているコメントを明確にするために書いています(JavaScriptのほとんどすべてについて言えることを忘れています)。

ノードモジュール

ノードにWebワーカーを追加することになっているいくつかのモジュールがあります。

私はそれらのいずれも使用していませんが、関連する可能性のある2つの簡単な観察があります。2015年3月の時点で、node-webworkerは4年前に最後に更新され、node-webworker-threadsは1か月前に最後に更新されました。また、node-webworker-threadsの使用例では、ファイル名の代わりに関数をWorkerコンストラクターへの引数として使用できることがわかります。これは、メモリを共有するスレッドを使用して実装されている場合、微妙な問題を引き起こす可能性があります(ただし、 functionsは.toString()メソッドでのみ使用され、それ以外の場合は別の環境でコンパイルされます。その場合は問題ない可能性があります-ここで私の観察を共有するだけで、より深く調査する必要があります)。

NodeにWebワーカーAPIを実装する他の関連プロジェクトがある場合は、コメントを残してください。

アップデート1

執筆の時点ではまだわかりませんでしたが、この回答を書く1日前に偶然、Webワーカーがio.jsに追加されました

io.jsはNode.jsのフォークです-詳細については、io.jsがNode.js をフォークすることにした理由、Mikeal RogersへのInfoWorldインタビューを参照してください。)

WebワーカーにはJavaScriptの一般的な哲学、特に同時実行性に関するノードに反するものは何もないという点を証明するだけでなく、WebワーカーがioのようなサーバーサイドJavaScriptのファーストクラスの市民になる可能性があります。 js(および将来的にはNode.js)は、最新のすべてのブラウザーのクライアント側JavaScriptと同じです。

アップデート2

Update 1と私のツイートでは、io.jsのプルリクエスト#1159 を参照していましたこれは 7月8日に閉じられ、まだ開いているノードPR#2133に置き換えられたノードPR#1159にリダイレクトされ ます。これらのプルリクエストのもとで行われている議論により、io.js / Node.jsのWebワーカーのステータスに関する最新の情報が提供される場合があります。

アップデート3

最新情報 -コメントに投稿していただいたNiCk Newmanに感謝します。2015年9月6日から、Petka Antonovによるワーカーの初期実装コミットがダウンロードされ、このツリーで試すことができます 。詳細はNiCk Newmanのコメントを参照してください。

アップデート4

2016年5月の時点で、まだオープンなPR#2133-ワーカーに関する最後のコメント:初期実装は3か月前のものでした。5月30日、Matheus Moreiraは私に以下のコメントでこの回答の更新を投稿するように依頼し、PRコメントでこの機能の現在のステータス要求しました

PRディスカッションの最初の回答は懐疑的でしたが、後でベンノールドウイス「これを何らかの形でマージすることは私のv7のToDoリストにあります」と書いています。

他のすべてのコメントは2番目のようで、2016年7月の時点で、2016年10月にリリースされる予定の次のバージョンのノードであるバージョン7.0 (必ずしもこの正確なPRの形式ではない)でWebワーカーが利用可能になるはずです

コメントで指摘し、GitHubでの議論を復活させてくれたMatheus Moreiraに感謝します。

アップデート5

2016年7月の時点で、npmには以前は利用できなかったモジュールがいくつかあります。関連するモジュールの完全なリストについては、npmでワーカー、Webワーカーなどを検索してください。特にうまく機能しないものがある場合は、投稿してくださいコメント。

アップデート6

2017年1月の時点で、ウェブワーカーがNode.jsに統合されることはほとんどありません。

プルリクエスト#2133 ワーカー: 2015年7月8日からのペトカアントノフによる最初の実装は、2016年12月11日にBen Noordhuisによって最終的に閉じられました。また、共有メモリやより効率的なシリアル化などの従来の手段を使用してそれを実現することもできます。」

詳細については、GitHubのPR 2133へのコメントを参照してください。

コメントで指摘してくれたMatheus Moreiraに再度感謝します。

アップデート6

数日前に、2018年6月--experimental-workerフラグでアクティブ化された試験的な機能として、ノードv10.5.0にWebワーカーが登場したことを嬉しく思います。

詳細については、以下を参照してください。

🎉🎉🎉やっと!私は3年前のStack Overflowの回答に7回目の更新を行うことができます。ここでは、la Webワーカーのスレッド化はNodeの哲学に反するものではなく、今回はようやく取得したと述べています。😜👍


1
@NiCkNewmanありがとう。io.jsの元のプルリクエストは現在閉じられており、別のプルリクエストに置き換えられています。GitHubのプルリクエストのコメントでいくつかのディスカッションがあり、そこにいくつかの情報が見つかるでしょう。参照:私の回答のUpdate 2。
rsp

1
はい、彼らは最後のlibuvの問題を修正したようです。モジュールをいつ手に入れられるのかしら。待つことができない!私たちを更新してくれてありがとう〜編集:ちょうど初期化されました:github.com/petkaantonov/io.js/commit/…さあ、いよいよ始まります!
NiCk Newman、2015

1
うん、それはライブです。(まだ正式には実装されていません)しかし、github.com / petkaantonov / io.js / tree / からソースをダウンロードして、テストしたい場合はコンパイルできます。私は今それをやっている〜
ニック・ニューマン

1
@NiCkNewman新しい情報をありがとう-私はそれを答えに追加しました。
rsp

1
Node.js workers実装のステータスを更新していただけますか?PR#2133の最新のコメントは2月のものです。開発者は明らかに問題に遭遇し、それが解決されたことを示すコメントはありません。
Matheus Moreira 2016年

8

私は、ソフトウェアを高速にするためにマルチスレッドを使用していた古い考え方の出身です。過去3年間、私はNode.jsとその大きな支持者を使用しています。hasanyasinがnodeの仕組みと非同期機能の概念を詳しく説明したように。しかし、ここにいくつか追加します。

昔はシングルコアでクロック速度が遅いため、ソフトウェアを高速かつ並列に動作させるためにさまざまな方法を試しました。DOS日では、一度に1つのプログラムを実行するために使用します。Windowsよりも、複数のアプリケーション(プロセス)を一緒に実行し始めました。テストされた場合のプリエンプティブおよび非プリエンプティブ(または協調)などの概念。プリエンプティブがシングルコアコンピューターでのより良いマルチプロセッシングタスクの答えであることを、私たちは今知っています。それに伴い、プロセス/タスクおよびコンテキスト切り替えの概念が登場しました。スレッドの概念よりも、プロセスコンテキストの切り替えの負担をさらに軽減します。新しいプロセスを生成する代わりに、軽量の代替として作成されたスレッド。

つまり、シグナルを送信するか、マルチコアまたはシングルコアを送信しないかによって、プロセスはプリエンプトされ、OSによってタイムスライスされます。

Nodejsは単一のプロセスであり、非同期メカニズムを提供します。ここでは、タスクが完了するのをイベントループで待機している間に、ジョブを実行しているタスクを実行するOSにディスパッチします。OSから緑の信号を受け取ったら、必要なことをすべて実行します。ある意味で、これは協調的/非プリエンプティブなマルチタスク処理であるため、非常に長い時間イベントループをブロックしないでください。そうしないと、アプリケーションが非常に速く劣化します。
したがって、本来ブロックしているタスクや非常に時間がかかるタスクがある場合、OSとスレッドのプリエンプティブな世界にそれを分岐する必要があります。これの良い例はlibuvのドキュメントにあります。また、ドキュメントをさらに読むと、FileI / Oがnode.jsのスレッドで処理されていることがわかります。

したがって、まず、すべてがソフトウェアの設計です。第二に、コンテキストの切り替えは、彼らがあなたに何を言っても、常に起こっています。スレッドが存在するのには理由がありますが、その理由は、プロセス間を切り替える方が速いためです。

node.jsの内部では、すべてのc ++とスレッドです。そして、nodeはc ++で機能を拡張し、必要なスレッドを使用して速度をさらに上げる方法を提供します。つまり、ソースからの読み取り、ソースへの書き込み、大規模データ分析などのタスクをブロックします。

私はhasanyasinの答えが受け入れられたものであることを知っていますが、私にとっては、あなたが何を言っても、どのようにスクリプトの後ろに隠しても、スレッドは存在します。そして、スレッドはNode.jsのバックボーンにあるので、完全にbashする前にマルチスレッドは正しいです。また、スレッドはプロセスとは異なり、コアあたりのノードプロセスの制限はスレッドの数に正確には適用されません。スレッドはプロセスのサブタスクのようなものです。実際、スレッドは勝ち、WindowsタスクマネージャやLinuxのtopコマンドには表示されません。もう一度、彼らはプロセスよりも少し軽量です


非同期コードは大きな革新ではなく(実際、何十年にもわたって使用されてきました)、マルチスレッドは、置き換えられる非推奨のテクノロジではありません。これらはさまざまなトレードオフを持つさまざまなツールであり、実際には非常にうまく組み合わせることができます。node-clusterを実行するたびに、実際には複数の「スレッド」(この場合はプロセスですが、スレッドを使用して同じことを実現でき、さらに軽量化できます)を実行します。または、何千ものグリーンスレッドを実行できるErlangまたはGoを使用してください...
Hejazzman

私たちが見落としている主要な点は、OSの下でのプロセスは常に公平性を提供するために予防的な方法で行われるということです。また、マルチプロセッサを使用すると、実際に並列コードを実行できますが、それでもプリエンプションがあります。非同期処理は、一部のプロセスのOSでも実行されます。
リンプラッシュ

4

この場合、Webワーカーが関連しているかどうかはわかりませんが、web.workerはクライアント側の技術(ブラウザーで実行)であり、node.jsはサーバーで実行されます。私が理解している限り、ファイバーもブロックしています。つまり、ファイバーは自発的なマルチタスクであるため、使用できますが、を介してコンテキストスイッチを自分で管理する必要がありますyield。スレッドは実際にはあなたが必要とするものかもしれませんが、node.jsでのスレッドの成熟度はわかりません。


3
参考までに、webworkersは(部分的に)node.jsに適合しています。そしてnode-workersパッケージとして利用できます。これを見てください:github.com/cramforce/node-worker
Parth Thakkar

知ってよかった、ありがとう。ただし、ドキュメントは非常に少なく、別のスレッドで実行するか、プロセスで実行するか、または単に同じプロセスで実行するかはわかりません。また、コードを掘り下げる時間もないので、どうなるかわかりません。あなたのケースのために働きます。
lanzz

@ParthThakkar:そのプロジェクトは3年間(投稿したときは2)触れられておらず、0.0.1を超えていません。
mpen 2013年

@Mark:私がそのことを知らなかった理由は、私がまだプロのプログラマではないためです。ええと、私は大学にも入っていません。私はまだ高校生で、学校の仕事を管理する以外にも、プログラミングについて読み続けています。したがって、私がそのような問題すべてについて知識を持つことは遠くに不可能です。私は自分が知っていることを投稿しました...
Parth Thakkar 2013年

@マーク:プロジェクトの歴史についてそれを指摘してくれてうれしかったですが。そんなことは今後の対応でやっていきます!! :)
Parth Thakkar 2013年

3

worker_threadsで実装され、フラグの後ろに出荷されましたnode@10.5.0。それはまだ初期の実装であり、将来のリリースでより効率的にするために、より多くの努力が必要です。最新で試してみる価値があるnode


2

多くのNode開発者の意見では、Nodeの最良の部分の1つは、実際にはそのシングルスレッドの性質です。スレッドは、ノードが非ブロッキングIOのみを実行することによって完全に回避する共有リソースに、多くの困難をもたらします。

Nodeが単一スレッドに限定されていると言っているのではありません。スレッド化された並行性を取得する方法が、求めているものと異なるだけです。スレッドを処理する標準的な方法は、Node自体に標準で付属しているクラスターモジュールを使用することです。これは、コード内でスレッドを手動で処理するよりも、スレッドへのアプローチが簡単です。

コード内で非同期プログラミングを処理する場合(ネストされたコールバックピラミッドを回避する場合など)、Fibersライブラリの[Future]コンポーネントは適切な選択です。ファイバーに基づいたAsyncblockをチェックすることもお勧めします。ファイバーは、スタックを複製し、必要に応じてシングルスレッドでスタック間をジャンプすることで、コールバックを非表示にできるので便利です。利点を提供しながら、実際のスレッドの面倒を省きます。欠点は、ファイバーを使用するとスタックトレースが少し変になる可能性があることですが、それほど悪くはありません。

非同期のものについて心配する必要がなく、ブロックせずに多くの処理を行うことに関心がある場合は、process.nextTick(callback)を時々呼び出すだけで十分です。


まあ、あなたの提案-クラスターについて-は私が最初に考えたものでした。しかし、その問題はオーバーヘッドです。新しいプロセスがフォークされるたびに、v8の新しいインスタンスを初期化する必要があります(〜30ms、10MB)。したがって、それらをたくさん作成することはできません。これは、ノードのドキュメントから直接取得されます。これらの子ノード(child_processesについて)は、まだV8のまったく新しいインスタンスです。新しいノードごとに少なくとも30msの起動と10mbのメモリを想定します。つまり、何千ものそれらを作成することはできません。
Parth Thakkar 2012年

1
これはまさにクラスターの考え方です。CPUコアごとに1つのワーカーを実行します。これ以上はおそらく不要です。CPUを集中的に使用するタスクでも、非同期スタイルで正常に動作します。ただし、本格的なスレッドが本当に必要な場合は、完全に別のサーバーのバックエンドに移動することを検討する必要があります。
genericdave、2012年

1

たぶん、実行しているタスクに関するいくつかの情報が役立つでしょう。(genericdaveの回答に対するコメントで述べたように)何千ものそれらを作成する必要があるのはなぜですか?Nodeでこの種のことを行う通常の方法は、常に実行され、メッセージを使用して通信できるワーカープロセス(forkまたはその他のメソッドを使用)を起動することです。つまり、実行しているタスクを実行する必要があるたびに新しいワーカーを起動するのではなく、単に実行中のワーカーにメッセージを送信し、完了したら応答を取得するだけです。正直なところ、何千もの実際のスレッドを起動することも非常に効率的であるとは思えません。CPU によって制限されています。

さて、これらすべてを言った後、私は最近、Hook.ioで多くの作業を行っています。これは、この種のオフロードタスクを他のプロセスにオフロードするのに非常にうまく機能しているようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.