Skip to content

Instantly share code, notes, and snippets.

@drbobbeaty
Created March 3, 2011 17:15
Show Gist options
  • Save drbobbeaty/853122 to your computer and use it in GitHub Desktop.
Save drbobbeaty/853122 to your computer and use it in GitHub Desktop.
Erlang Ring Benchmark from Erlang book by J Armstrong (Chapter 8 Exercises)
-module(ring).
-export([start/0, test/2]).
%% make the state container for the ring node
-record(state, {next, origin, caller}).
%% standard entry point for a 1000 node, 500 cycle test
start() ->
test(1000, 500).
%% make a synchronous message call to the pid and wait for response
rpc(Pid, Request) ->
Pid ! {self(), Request},
receive
{Pid, Response} ->
Response
end.
%% main messaging loop for all nodes in the ring
loop(State) ->
receive
%% the head of the ring needs to know it's the origin
{From, {origin, Origin}} ->
From ! {self(), Origin},
loop(State#state{origin=Origin});
%% building the ring is a countdown of creations
{From, {build, Count}} when Count > 1 ->
Node = spawn(fun() -> loop(State) end),
rpc(Node, {build, Count-1}),
From ! {self(), Count},
loop(State#state{next=Node});
%% ...to the final node that circles back to the origin
{From, {build, Count}} ->
From ! {self(), Count},
loop(State#state{next=State#state.origin});
%% starting the test kicks it off and saves the caller
{From, {go}} ->
State#state.next ! {self(), {ping}},
loop(State#state{caller=From});
%% the ping needs to answer and then stop or continue
{From, {ping}} ->
From ! {self(), {pong}},
if
State#state.origin =:= self() ->
State#state.caller ! {self(), 1};
true ->
State#state.next ! {self(), {ping}}
end,
loop(State);
%% ...the response to a pong is to do nothing
{_, {pong}} ->
loop(State)
end.
%% build a ring o 'N' nodes, and run through this 'M' times...
test(Nodes,Cycles) ->
io:format("starting the build and exercise of the ring...~n"),
statistics(runtime),
statistics(wall_clock),
State = #state{},
Head = spawn(fun() -> loop(State) end),
rpc(Head, {origin, Head}),
rpc(Head, {build, Nodes}),
_ = [rpc(Head, {go}) || _ <- lists:seq(1,Cycles)],
{_, Runtime} = statistics(runtime),
{_, Walltime} = statistics(wall_clock),
U1 = Runtime * 1000 / (Nodes*Cycles),
U2 = Walltime * 1000 / (Nodes*Cycles),
io:format("total cpu=~pms ... ~pus/op and wall=~pms ... ~pus/op~n", [Runtime, U1, Walltime, U2]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment