更新: この質問には、ベンチマークを無意味にするエラーが含まれています。F# と Erlang の基本的な同時実行機能を比較するより良いベンチマークを試み、別の質問で結果を調べます。
Erlang と F# のパフォーマンス特性を理解しようとしています。Erlang の並行性モデルは非常に魅力的ですが、相互運用性の理由から F# を使用する傾向があります。すぐに使用できる F# は、Erlang の同時実行プリミティブのようなものを提供しませんが、async と MailboxProcessor は、Erlang がうまく機能することのごく一部しかカバーしていないことがわかります.F# のパフォーマンスで何が可能かを理解しようとしています。賢い。
Joe Armstrong の Programming Erlang の本で、彼は Erlang ではプロセスが非常に安価であると主張しています。彼は、(大まかに) 次のコードを使用して、この事実を示しています。
-module(processes).
-export([max/1]).
%% max(N)
%% Create N processes then destroy them
%% See how much time this takes
max(N) ->
statistics(runtime),
statistics(wall_clock),
L = for(1, N, fun() -> spawn(fun() -> wait() end) end),
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
lists:foreach(fun(Pid) -> Pid ! die end, L),
U1 = Time1 * 1000 / N,
U2 = Time2 * 1000 / N,
io:format("Process spawn time=~p (~p) microseconds~n",
[U1, U2]).
wait() ->
receive
die -> void
end.
for(N, N, F) -> [F()];
for(I, N, F) -> [F()|for(I+1, N, F)].
私の Macbook Pro では、10 万のプロセス ( processes:max(100000)) を生成して強制終了するには、プロセスごとに約 8 マイクロ秒かかります。プロセスの数をもう少し増やすことはできますが、100 万を超えるとかなり一貫して問題が発生するようです。
F# をほとんど知らないので、async と MailBoxProcessor を使用してこの例を実装しようとしました。間違っている可能性がある私の試みは次のとおりです。
#r "System.dll"
open System.Diagnostics
type waitMsg =
| Die
let wait =
MailboxProcessor.Start(fun inbox ->
let rec loop =
async { let! msg = inbox.Receive()
match msg with
| Die -> return() }
loop)
let max N =
printfn "Started!"
let stopwatch = new Stopwatch()
stopwatch.Start()
let actors = [for i in 1 .. N do yield wait]
for actor in actors do
actor.Post(Die)
stopwatch.Stop()
printfn "Process spawn time=%f microseconds." (stopwatch.Elapsed.TotalMilliseconds * 1000.0 / float(N))
printfn "Done."
Mono で F# を使用すると、100,000 個のアクター/プロセッサの起動と停止にかかる時間はプロセスあたり 2 マイクロ秒未満で、Erlang よりも約 4 倍高速です。さらに重要なのは、何百万ものプロセスに問題なくスケールアップできることです。100 万または 200 万のプロセスを開始するには、プロセスごとに約 2 マイクロ秒かかります。2000 万のプロセッサを起動することはまだ可能ですが、プロセスあたり約 6 マイクロ秒まで遅くなります。
F# が async と MailBoxProcessor を実装する方法を完全に理解するにはまだ時間がかかりましたが、これらの結果は心強いものです。私がひどく間違っていることはありますか?
そうでない場合、Erlang が F# よりも優れている可能性が高い場所はありますか? Erlang の同時実行プリミティブをライブラリを介して F# に持ち込めない理由はありますか?
編集: ブライアンが指摘したエラーのため、上記の数値は間違っています。修正したら、質問全体を更新します。