Skip to content

Instantly share code, notes, and snippets.

@shino
Created October 28, 2008 06:00
Show Gist options
  • Save shino/20309 to your computer and use it in GitHub Desktop.
Save shino/20309 to your computer and use it in GitHub Desktop.
-module(simple_counter3).
-behaviour(gen_server).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-export([terminate/2, code_change/3]).
a
-export([increment/0, stop/0]).
-export([count_to/1, test/0]).
-define(INTERVAL, 100000).
-define(CLIENT_INTERVAL, 100000).
-record(state, {count, before}).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], _Opts = []).
init(_Args) ->
{ok, #state{count = 1, before = erlang:now()}}.
terminate(_Reason, _Status) ->
p("terminate with state", _Status),
ok.
do_increment(#state{count = Count, before = Before} = _State) when Count rem ?INTERVAL == 0 ->
NewBefore = erlang:now(),
ElapsedTime = timer:now_diff(NewBefore, Before),
p("server", {Count, [nan, ElapsedTime], ?INTERVAL/ElapsedTime*1000}),
{reply, Count + 1, #state{count = Count + 1, before = NewBefore}};
do_increment(#state{count = Count} = State) ->
{reply, Count + 1, State#state{count = Count + 1}}.
handle_call(increment, _From, State) ->
do_increment(State).
handle_cast(stop, State) ->
{stop, normal, State};
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
code_change(_OldVsn, Count, _Extra) ->
{ok, Count}.
%% -- client API below --
increment() ->
gen_server:call(?MODULE, increment).
stop() ->
gen_server:cast(?MODULE, stop).
%% -- benchmark code below --
test() ->
p("bench ", benchmark_note()),
start_link(),
lists:map(
fun (Processes) ->
test_in_parallel(
Processes,
lists:map(fun (E) -> round(math:pow(10,E)) end,
lists:seq(4,4))) end,
lists:seq(10, 80, 10)),
stop(),
ok.
test_in_parallel(Processes, Targets) ->
p("Client processes", Processes),
lists:map(
fun(Target) ->
p("bench ",
benchmark(
fun () ->
rpc:pmap({?MODULE, count_to}, [],
lists:duplicate(Processes, Target)),
Target*Processes
end)) end,
Targets),
ok.
count_to(Target) ->
count_to(Target, 0).
count_to(Target, Target) ->
Target;
count_to(Target, Count) ->
increment(),
count_to(Target, Count + 1).
benchmark(TargetFunction) ->
lists:foreach(fun statistics/1, benchmark_elements()),
Result = TargetFunction(),
Times = lists:map(
fun (Type) -> {_, T} = statistics(Type), T end,
benchmark_elements()
),
{Result, Times, Result/lists:last(Times)}.
benchmark_elements() ->
[runtime, wall_clock].
benchmark_note() ->
{result, benchmark_elements(), 'per msec'}.
p(Label, Message) ->
io:format("~s: ~p~n", [Label, Message]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment