# [erlang-questions] ring benchmark results: Is Erlang crazy fast?

David Cabana < >
Sat Jul 21 15:58:14 CEST 2007

```Joe Armstrong proposed an exercise in Programming Erlang :
"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 did so, but I am having a hard time accepting the results. I am
running latest the DarwinPorts build of Eralang on a G4 PowerBook.
I'll post results, my reservations, and source code in that order.

%% --- results, pasted from console session
Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0]
[hipe] [kernel-poll:false]

Eshell V5.5.5  (abort with ^G)
1> c(ring).
{ok,ring}
2> ring:start(5000,10).
Total time=10 (32) milliseconds
ok
3> ring:start(5000,10000).
Total time=20 (26) milliseconds
ok
4> ring:start(5000,10000000).
Total time=10 (36) milliseconds

I find it hard to believe Erlang can send 50 billion messages in 36
milliseconds on my hardware.  Can anyone give me a sanity check here?

Here's the code.  I left in some (commented out) diagnostic code;
using it with small values of M and N leads me to think the program
is doing what it is supposed to do. I am an Erlang newb; this is the
longest and least trivial Erlang program I've written. Any
observations on better style would be welcome.

-module(ring).
-export([start/2, foo/1, bar/0]).
%%
%% per Armstrong's "Programming Erlang"
%% 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.
%%

foo(Next) ->
element in {x,y}, only bar does
{0, Any} ->
% io:format("foo done ~n",[]),
Next ! {0, Any};	%% send the 0 along to tell everyone to shut down
{N, Any} ->
% io:format("  foo ~p  ~n", [N]),
Next ! {N-1, Any},
foo(Next);
Other -> io:format("foo: huh? ~p ~n", [Other])
end.

bar() ->
{0, Next} ->
% io:format("bar done ~n",[]),
Next ! {0, Next};
{N, Next} ->
% io:format("bar ~p  ~n", [N]),
Next ! {N-1, Next},
bar();
Other -> io:format("bar: huh? ~p ~n", [Other])
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) ->
statistics(runtime),
statistics(wall_clock),

A= spawn(ring, bar, []),
B= chain(N-1, A),
A ! {N*M, B},

{_, RT} = statistics(runtime),
{_, WC} = statistics(wall_clock),
io:format("Total time=~p (~p) milliseconds~n", [RT, WC]).

```