Created
March 3, 2011 17:15
-
-
Save drbobbeaty/853122 to your computer and use it in GitHub Desktop.
Erlang Ring Benchmark from Erlang book by J Armstrong (Chapter 8 Exercises)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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