1. ホーム
  2. concurrency

[解決済み] 関数型言語(特にErlang)はどのように/なぜうまくスケールするのですか?

2023-03-18 14:41:28

質問

以前から、関数型プログラミング言語や機能の知名度が上がってきているのを見ていました。調べてみても、その魅力の理由がわかりませんでした。

そして最近、Kevin Smithの "Basics of Erlang" のプレゼンテーションに参加しました。 Codemash .

私はこのプレゼンテーションを楽しみ、関数型プログラミングの特性の多くが、スレッドや並行処理の問題を避けることをより簡単にするものであることを学びました。ステートとミュータビリティがないため、複数のスレッドが同じデータを変更することは不可能だと理解していますが、Kevin は (私が正しく理解していれば) すべての通信はメッセージを通じて行われ、メッセージは同期的に処理される (これも並行処理の問題を回避する) と述べています。

しかし私はErlangが非常にスケーラブルなアプリケーションで使われていることを読みました(これがEricssonが最初にこれを作った理由です)。もしすべてが同期的に処理されるメッセージとして処理されるのであれば、1秒間に何千ものリクエストを効率的に処理することができるでしょうか?私たちが非同期処理に移行し始めたのは、複数のスレッドで同時に処理を実行することでスケーラビリティを実現するためではないでしょうか?このアーキテクチャは、安全ではありますが、スケーラビリティの点では後退しているように思えます。私は何を見逃しているのでしょうか?

Erlangの作成者が並行処理の問題を避けるために意図的にスレッドのサポートを避けたことは理解していますが、スケーラビリティを実現するためにはマルチスレッドが必要だと思ったのですが、どうでしょうか?

関数型プログラミング言語が本質的にスレッドセーフでありながら、スケーラブルであるためにはどうしたらよいのでしょうか?

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

関数型言語は、(一般に) 変異する に依存しません。このため、変数の値は固定されているので、変数の共有状態を保護する必要がありません。その結果、従来の言語がプロセッサやマシンにまたがってアルゴリズムを実装するために経験しなければならない、輪廻転生の大部分を回避することができるのです。

Erlangは伝統的な関数型言語よりもさらに進んで、メッセージパッシングシステムを組み込んで、コード片がメッセージの受信とメッセージの送信だけを気にするイベントベースのシステムで全てが動作するようにしています。

これは何を意味するかというと、プログラマはメッセージが別のプロセッサやマシンで処理されることに(名目上)無関心で、単にメッセージを送信するだけで十分なのです。メッセージを送信するだけで十分です。 別のメッセージ .

この結果、各スニペットは他のすべてのスニペットから独立しています。共有コード、共有ステート、およびすべてのインタラクションは、多くのハードウェア間で分散可能なメッセージ システムから来るものではありません (または、そうでないものもあります)。

従来のシステムと比較すると、変数とコード実行の周りにミューテックスとセマフォを配置する必要があります。スタックを介した関数呼び出しでは、タイトなバインディングを行います (リターンが発生するのを待ちます)。これらすべてがErlangのようなシェアードナッシングシステムではあまり問題にならないボトルネックを生み出します。

EDIT: Erlangは非同期であることも指摘しなければなりません。あなたがメッセージを送ると、たぶんいつか別のメッセージが戻ってくるでしょう。そうでない場合もあります。

スペンサーが指摘したout of order executionも重要で、よく答えてくれています。