1. ホーム
  2. multithreading

[解決済み] 技術的に、なぜErlangのプロセスはOSのスレッドよりも効率的なのですか?

2022-04-16 01:59:44

質問

Erlangの特徴

から Erlang プログラミング (2009):

Erlangの並行処理は高速でスケーラブルです。Erlangのプロセスは軽量で、Erlang仮想マシンはプロセスを作成するたびにOSスレッドを作成するわけではありません。プロセスは仮想マシン内で作成、スケジューリング、処理され、オペレーティングシステムに依存しません。その結果、プロセスの作成時間はマイクロ秒のオーダーで、同時に存在するプロセスの数には依存しません。これをJavaやC#と比較してみてください。JavaではプロセスごとにOSのスレッドが作成されます:非常に競争力のある比較になりますが、Erlangはどちらの言語も大きく凌駕しています。

より Erlangの並行処理指向プログラミング (pdf) (スライド) (2003):

Erlangのプロセス作成にかかる時間は、2,500プロセスまでは1μsと一定ですが、それ以降は30,000プロセスまで約3μsに増加することがわかります。図の上部にJavaとC#のパフォーマンスを示しています。プロセス数が少ない場合、プロセスの作成に約300µsかかります。2,000以上のプロセスを作成することは不可能です。

3万プロセスまでなら、2つのErlangプロセス間でメッセージを送信する時間は約0.8μsであることがわかります。C#では最大プロセス数(約1800プロセス)まで、1メッセージあたり約50µsかかりました。Javaはさらに悪く、100プロセスまでは1メッセージあたり約50µsで、その後1000プロセスくらいになると1メッセージあたり10msと急激に増加しました。

私の考え

なぜErlangのプロセスが新しいプロセスを生成するのにとても効率的で、プロセスあたりのメモリフットプリントがずっと小さいのか、技術的に完全に理解できていません。OSとErlang VMの両方がスケジューリングやコンテキストスイッチをしなければならず、レジスタの値などを追跡しなければならないからです。

単純に、なぜOSのスレッドはErlangのプロセスと同じように実装されないのでしょうか?もっと何かサポートしなければならないのでしょうか?そしてなぜより大きなメモリフットプリントが必要なのでしょうか?そしてなぜスレッドの起動や通信が遅いのでしょう?

技術的に、スポーンや通信に関して、なぜErlangのプロセスの方がOSのスレッドよりも効率的なのでしょうか?そしてなぜOSのスレッドは同じように効率的に実装・管理できないのでしょうか?そしてなぜOSのスレッドは大きなメモリフットプリントがあり、さらにスポーンや通信が遅いのでしょうか?

もっと読む

解決方法は?

いくつかの要因があります。

  1. ErlangのプロセスはOSのプロセスではありません。Erlang VMによって軽量な協調スレッドモデルを使って実装されています(Erlangレベルではプリエンプティブですが、協調的にスケジュールされたランタイムのコントロールの下にあります)。これはコンテキストの切り替えがとても安く、既知の制御されたポイントで切り替えるだけなので、CPUの状態(通常、SSEやFPUレジスタ、アドレス空間マッピングなど)全体を保存する必要がないことを意味します。
  2. Erlangプロセスは動的に割り当てられたスタックを使います。スタックはとても小さく始まり、必要に応じて大きくなります。これによって利用可能なRAMを使い切ることなく、何千、何百万ものErlangプロセスを生成することができます。
  3. Erlangはかつてシングルスレッドでした。つまり、プロセス間のスレッドセーフを確保する必要がありませんでした。現在ではSMPをサポートしていますが、同じスケジューラ/コア上のErlangプロセス間のやりとりはまだとても軽量です(コアごとに個別のランキューがあります)。