I’ve been reading Joe Armstrong’s excellent Programming Erlang. In it he proposes an exercise:
Write a ring benchmark. Create N processes in a ring. Send a message round the ring M times. So that a total of N * M messages get sent. Time how long this takes for different values of N and M.
I found the exercise very instructive. My solution follows.
-module(ring).
-export([start/2, foo/1, bar/1, timer/0]).
%%----------------------------------------------------
%% Create N processes in a ring.
%% Send a message round the ring M times,
%% so that N * M messages get sent.
%% Time performance for different values of N and M.
%%----------------------------------------------------
foo(Next) ->
receive
{0, Any} ->
Next ! {0, Any}; %% send the 0 to tell everyone to shut down
{N, Any} ->
Next ! {N, Any},
foo(Next)
end.
bar(Timer) ->
receive
{0, Next} ->
Timer ! done,
Next ! {0, Next};
{N, Next} ->
Next ! {N-1, Next},
bar(Timer)
end.
timer() ->
statistics(runtime),
statistics(wall_clock),
receive
done ->
{_, RT} = statistics(runtime),
{_, WC} = statistics(wall_clock),
io:format("Total time=~p (~p) milliseconds~n", [RT, WC])
end.
%%----------------------------------------------------
%% construct a chain of processes
%% process J-1 routes msgs to process J for all J < K
%%----------------------------------------------------
chain(0, Pid) -> Pid;
chain(K, Pid) ->
chain(K-1, spawn(ring,foo,[Pid])).
%%----------------------------------------------------
%% N is the number of processes in the ring
%% M is the number of times msgs circle the ring
%%----------------------------------------------------
start(N, M) ->
%% N-1 processes are of type foo, one is of type bar
A= spawn(ring, bar, [spawn(ring, timer,[])]),
B= chain(N-1, A),
A ! {M, B}.

Posts