SPSBenchmark/src/benchmarker.erl

108 lines
3.7 KiB
Erlang

-module(benchmarker).
-export([init/0, startServiceTime/2, startOpenLoop/3,
startClosedLoop/4, stop/0, inactive/0]).
%% @spec init() -> void()
%% @doc Initialize the benchmark.
%% This must be done only the first time.
init() ->
application:start(spsBenchmark),
inets:start(),
ssl:start(),
statistician:init(),
BenchmarkerPid = spawn(?MODULE, inactive, []),
register(benchmarker, BenchmarkerPid).
%% @spec startServiceTime(Duration::integer(), Warmup::integer()) -> void()
%% @doc Start the benchmark to calculate the service time.
startServiceTime(Duration, Warmup) ->
benchmarker !
{start_benchmark, service_time, Duration * 1000, Warmup * 1000}.
%% @spec startOpenLoop(Rate::float(), Duration::integer(),
%% Warmup::integer()) -> void
%% @doc Start the benchmark in an open loop.
startOpenLoop(Rate, Duration, Warmup) ->
benchmarker !
{start_benchmark, open_loop, Rate, Duration * 1000, Warmup * 1000}.
%% @spec startClosedLoop(Rate::float(), NumWorkers::integer(),
%% Duration::integer(), Warmup::integer()) -> void()
%% @doc Start the benchmark in a closed loop.
startClosedLoop(Rate, NumWorkers, Duration, Warmup) ->
benchmarker !
{start_benchmark, closed_loop, Rate, NumWorkers,
Duration * 1000, Warmup * 1000}.
%% @spec stop() -> void
%% @doc Stop the benchmark.
stop() ->
benchmarker ! {stop_benchmark}.
%% @spec inactive() -> void()
%% @doc The benchmark is inactive, wait for a message to start.
inactive() ->
receive
{start_benchmark, service_time, Duration, Warmup} ->
RequesterPid = requester:init(),
erlang:monitor(process, RequesterPid),
requester:startServiceTime(RequesterPid),
io:format("Starting service time benchmark~n"),
warmup(RequesterPid, Duration, Warmup);
{start_benchmark, open_loop, Rate, Duration, Warmup} ->
RequesterPid = requester:init(),
erlang:monitor(process, RequesterPid),
requester:startOpenLoop(RequesterPid, Rate),
io:format("Starting open loop benchmark~n"),
warmup(RequesterPid, Duration, Warmup);
{start_benchmark, closed_loop, Rate, NumWorkers, Duration, Warmup} ->
RequesterPid = requester:init(),
erlang:monitor(process, RequesterPid),
requester:startClosedLoop(RequesterPid, Rate, NumWorkers),
io:format("Starting closed loop benchmark~n"),
warmup(RequesterPid, Duration, Warmup)
end.
%% @spec warmup(RequesterPid::pid(), Duration::integer(),
%% Warmup::integer()) -> void()
%% @doc Start the warmup and start recording statistics at the end of it.
warmup(RequesterPid, Duration, Warmup) ->
receive
{stop_benchmark} ->
RequesterPid ! {stop}
after Warmup ->
statistician:startRecording(),
active(Duration, RequesterPid)
end.
%% @spec active(Duration::integer(), RequesterPid::pid()) -> void()
%% @doc The benchmark is active, print the statistics
%% periodically and when the benchmark ends.
active(Duration, RequesterPid) ->
receive
{'DOWN', _MonitorReference, process, _Pid, _Reason} ->
io:format("Requester ended before benchmarker finished~n"),
statistician:printStatistics(),
statistician:stopRecording(),
inactive();
{stop_benchmark} ->
RequesterPid ! {stop}
after Duration ->
requester:printActiveWorkers(RequesterPid),
requester:stop(RequesterPid),
statistician:printStatistics(),
statistician:stopRecording(),
deactivate()
end.
%% @spec deactivate() -> void()
%% @doc The benchmark waits the requester to finish.
%% This make sure that there won't be any active requests
%% before starting a new benchmark.
deactivate() ->
receive
{'DOWN', _MonitorReference, process, _Pid, _Reason} ->
% io:format("Benchmarker is ready~n"),
inactive()
end.