Skip to content

Instantly share code, notes, and snippets.

@hakobe
Last active December 20, 2015 15:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakobe/6152686 to your computer and use it in GitHub Desktop.
Save hakobe/6152686 to your computer and use it in GitHub Desktop.
プログラミングErlang 8.11 練習問題
% リングのベンチマークを書いてみよう。N個のプロセスからなるリングを作り、1つのメッセージがリングをM回るようにして、
% 合計でN*Mのメッセージが送信されるようにする。さまざまなNとMの値について所要時間を計ってみよう。
-module(message_ring).
-export([benchmark/2]).
benchmark(N,M) ->
RingNodes = for(1, N, fun() -> spawn( fun() -> ring_node() end) end),
[FirstRingNode|_] = RingNodes,
connect(RingNodes, FirstRingNode),
statistics(runtime),
statistics(wall_clock),
FirstRingNode ! {M, FirstRingNode, self()},
receive
finish ->
io:format("finish!!!~n"),
finish
end,
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
U1 = Time1 * 1000 / (N * M),
U2 = Time2 * 1000 / (N * M),
io:format("N(~p) x M(~p) : time per message passing = ~p (~p) microseconds, total = ~p (~p) milliseconds ~n", [N, M, U1, U2, Time1, Time2]).
connect(RingNodes, FirstRingNode) ->
case RingNodes of
[RingNode|[]] ->
RingNode ! {start, FirstRingNode};
[RingNode, NextRingNode|T] ->
RingNode ! {start, NextRingNode},
connect([NextRingNode|T], FirstRingNode)
end.
ring_node() ->
receive
{start, NextNode} ->
messenger(NextNode);
_ ->
void
end.
messenger(NextRingNode) ->
ThisNode = self(),
receive
{0, ThisNode, Benchmarker} -> % M周おわったら終了をお知らせ
Benchmarker ! finish,
NextRingNode ! die;
{M, ThisNode, Benchmarker} -> % わたってきたFirstRingNode が自分だったら次の周にうつる
NextRingNode ! {M - 1, ThisNode, Benchmarker},
messenger(NextRingNode);
{M, FirstRingNode, Benchmarker} -> % FirstRingNode ではない場合は次にメッセージを送るだけ
NextRingNode ! {M, FirstRingNode, Benchmarker},
messenger(NextRingNode);
die ->
NextRingNode ! die
end.
for(N, N, F) -> [ F() ];
for(I, N, F) -> [ F() | for(I+1, N, F) ].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment