Skip to content

Commit

Permalink
Implement optional runner label (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
williamthome authored Aug 8, 2024
1 parent bb4913e commit 9237f00
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 15 deletions.
1 change: 1 addition & 0 deletions CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ erlperf --init_runner '2.' 'run(1) -> ok.' 'run(2) -> ok.' --init_runner '1.'
| --init | Job initialisation code, see accepted callable formats below |
| --init_runner | Worker initialisation code |
| --done | Job cleanup code |
| --label | Runner label |
| | |
| --init_all | Default init code for all runners that do not have a specific code |
| --init_runner_all | Default init_runner code |
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ A benchmark may define following functions:
* **init** (optional): executed once when the job starts
* **done** (optional): executed once when the job is about to stop
* **init_runner** (optional): executed on every worker process startup
* **label** (optional): string that overrides the code value in reports
See `erlperf_job` for the detailed reference and ways to define a function (**callable**).
Expand Down Expand Up @@ -271,7 +272,7 @@ This is the default report form when less than 10 samples were collected.
Use `-r basic` to force basic reports with 10 and more samples.
Basic report contains following columns:
* **Code**: Erlang code supplied to the benchmark
* **Code**: Erlang code or label supplied to the benchmark
* **||**: how many concurrent processes were running. In the timed mode, it is always 1. In the concurrency
estimation mode, the number that achieved the highest total throughput (QPS)
* **QPS**: average number of runner code *iterations* (throughput). Measure per single *sample_duration*
Expand Down
33 changes: 22 additions & 11 deletions src/erlperf_cli.erl
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ main(Args) ->

%% find all runners
Code0 = [parse_code(C) || C <- maps:get(code, ParsedOpts)],
%% find associated init, init_runner, done
%% find associated init, init_runner, done, label
{_, Codes} = lists:foldl(fun callable/2, {ParsedOpts, Code0},
[{init, init_all}, {init_runner, init_runner_all}, {done, done_all}]),
[{init, init_all}, {init_runner, init_runner_all}, {done, done_all}, {label, undefined}]),

%% when isolation is requested, the node must be distributed
RunOpts = case is_map_key(isolation, ParsedOpts) of
Expand Down Expand Up @@ -205,7 +205,7 @@ benchmark(Codes, RunOpts, ConcurrencyTestOpts, false) ->
erlperf:benchmark(Codes, RunOpts, ConcurrencyTestOpts);
benchmark(Codes, RunOpts, ConcurrencyTestOpts, true) ->
[begin
io:format(">>>>>>>>>>>>>>> ~-32ts ~n", [format_code(maps:get(runner, C))]),
io:format(">>>>>>>>>>>>>>> ~-32ts ~n", [format_code(C)]),
[io:format("~ts~n", [L]) || L <- erlperf_job:source(C)],
io:format("<<<<<<<<<<<<<<< ~n")
end|| C <- Codes],
Expand Down Expand Up @@ -345,6 +345,8 @@ arguments() ->
help => "done code", nargs => 1, action => append},
#{name => init_runner, long => "-init_runner",
help => "init_runner code", nargs => 1, action => append},
#{name => label, long => "-label", type => string,
help => "runner label", nargs => 1, action => append},
#{name => init_all, long => "-init_all",
help => "default init code for all runners"},
#{name => done_all, long => "-done_all",
Expand Down Expand Up @@ -400,7 +402,7 @@ remove_relative_column([H, D]) ->
remove_relative_column(HasRelative) ->
HasRelative.

format_report_line(MaxAvg, #{mode := timed, code := #{runner := Code}, result := #{average := Avg, stddev := StdDev,
format_report_line(MaxAvg, #{mode := timed, code := Code, result := #{average := Avg, stddev := StdDev,
iteration_time := IterationTime, p99 := P99, median := Median, samples := Samples},
run_options := #{concurrency := Concurrency}}, ReportFormat) ->
[
Expand All @@ -416,7 +418,7 @@ format_report_line(MaxAvg, #{mode := timed, code := #{runner := Code}, result :=
integer_to_list(erlang:round(MaxAvg * 100 / Avg)) ++ "%"
];

format_report_line(MaxAvg, #{code := #{runner := Code}, result := #{average := Avg, stddev := StdDev,
format_report_line(MaxAvg, #{code := Code, result := #{average := Avg, stddev := StdDev,
iteration_time := IterationTime, p99 := P99, median := Median, samples := Samples},
run_options := #{concurrency := Concurrency}}, _ReportFormat) when Avg > 0.5 ->
[
Expand All @@ -431,7 +433,7 @@ format_report_line(MaxAvg, #{code := #{runner := Code}, result := #{average := A
integer_to_list(erlang:round(Avg * 100 / MaxAvg)) ++ "%"
];

format_report_line(_MaxAvg, #{code := #{runner := Code}, result := #{samples := Samples},
format_report_line(_MaxAvg, #{code := Code, result := #{samples := Samples},
run_options := #{concurrency := Concurrency}}, _ReportFormat) ->
[
format_code(Code),
Expand Down Expand Up @@ -464,15 +466,24 @@ format_table([Header | Data] = Rows, Width) ->
viewport_width() ->
case io:columns() of {ok, C} -> C; _ -> 80 end.

format_code(Code) when is_tuple(Code) ->
format_code(#{label := Label}) when is_list(Label) ->
Label;
format_code(#{label := Label}) when is_binary(Label) ->
binary_to_list(Label);
format_code(#{label := undefined, runner := Runner}) ->
format_code_1(Runner);
format_code(#{runner := Runner}) ->
format_code_1(Runner).

format_code_1(Code) when is_tuple(Code) ->
lists:flatten(io_lib:format("~tp", [Code]));
format_code(Code) when is_tuple(hd(Code)) ->
format_code_1(Code) when is_tuple(hd(Code)) ->
lists:flatten(io_lib:format("[~tp, ...]", [hd(Code)]));
format_code(Code) when is_function(Code) ->
format_code_1(Code) when is_function(Code) ->
lists:flatten(io_lib:format("~tp", [Code]));
format_code(Code) when is_list(Code) ->
format_code_1(Code) when is_list(Code) ->
Code;
format_code(Code) when is_binary(Code) ->
format_code_1(Code) when is_binary(Code) ->
binary_to_list(Code).

warn_system(#{dynamic_trace := Trace} = System) when Trace =/= none ->
Expand Down
5 changes: 4 additions & 1 deletion src/erlperf_job.erl
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@
runner := callable(),
init => callable(),
init_runner => callable(),
done => callable()
done => callable(),
label => iodata()
}.
%% Code map contains definitions for:
%%
Expand All @@ -207,6 +208,8 @@
%% <li>`done/0,1' - called when the job terminates, to clean up any resources
%% that are not destroyed automatically. done/0 accepts the return of init/0.
%% Call is made in the context of the job controller</li>
%% <li>`label' - runner label displayed in reports.
%% By default, the runner code is converted to a string</li>
%% </ul>

%% Internal (opaque) type, please do not use
Expand Down
13 changes: 11 additions & 2 deletions test/erlperf_cli_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
full_report/1, basic_timed_report/1, full_timed_report/1,
recorded/1,
squeeze/0, squeeze/1, step/1,
init_all/0, init_all/1
init_all/0, init_all/1,
label/1
]).

%%--------------------------------------------------------------------
Expand All @@ -27,7 +28,8 @@ suite() ->

all() ->
[simple, concurrent, verbose, zero, compare, squeeze, step, usage, init, double,
triple, pg, mfa, full_report, basic_timed_report, full_timed_report, recorded, init_all].
triple, pg, mfa, full_report, basic_timed_report, full_timed_report, recorded, init_all,
label].

%%--------------------------------------------------------------------
%% helper functions
Expand Down Expand Up @@ -342,3 +344,10 @@ init_all(Config) when is_list(Config) ->
?assert(C3 > 5 andalso C3 < 11, {qps, C3}), %% 10 ms delay
?assert(R > R2), %% 5 ms delay is less than 2 ms
?assert(R2 > R3). %% 5 ms delay is more than 10 ms

% erlperf 'foo.' --label bar
label(Config) when is_list(Config) ->
Out = capture_io(
fun () -> erlperf_cli:main(["foo.", "--label", "bar"]) end),
[{Label, _, _, _}] = parse_out(Out),
?assertEqual("bar", Label).

0 comments on commit 9237f00

Please sign in to comment.