summaryrefslogtreecommitdiff
path: root/lib/megaco/examples/meas/megaco_codec_meas.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/examples/meas/megaco_codec_meas.erl')
-rw-r--r--lib/megaco/examples/meas/megaco_codec_meas.erl167
1 files changed, 101 insertions, 66 deletions
diff --git a/lib/megaco/examples/meas/megaco_codec_meas.erl b/lib/megaco/examples/meas/megaco_codec_meas.erl
index ae28fa43a0..ceeaa35504 100644
--- a/lib/megaco/examples/meas/megaco_codec_meas.erl
+++ b/lib/megaco/examples/meas/megaco_codec_meas.erl
@@ -46,11 +46,11 @@
%% API
%% Avoid warning for local function error/2 clashing with autoimported BIF.
-compile({no_auto_import,[error/2]}).
--export([start/0, start/1]).
+-export([start/0, start/1, start/2]).
-export([start1/0]).
%% Internal exports
--export([do_measure_codec/8, do_measure_codec_loop/7]).
+-export([do_measure_codec/7, do_measure_codec_loop/7]).
-export([flex_scanner_handler/1]).
@@ -74,6 +74,8 @@
-define(DEFAULT_MESSAGE_PACKAGE, megaco_codec_transform:default_message_package()).
+-define(DEFAULT_OPTS, #{verbose => true}).
+
-define(FTS(), formated_timestamp()).
@@ -87,18 +89,22 @@ start1() ->
start().
start() ->
- meas_init(1, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS).
+ meas_init(1, ?DEFAULT_OPTS, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS).
start([MessagePackage]) ->
- do_start(1, MessagePackage, ?MEASURE_CODECS);
+ do_start(1, ?DEFAULT_OPTS, MessagePackage, ?MEASURE_CODECS);
start(Factor) when is_integer(Factor) andalso (Factor > 0) ->
- do_start(Factor, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS);
+ do_start(Factor, ?DEFAULT_OPTS, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS);
start(MessagePackage) ->
- do_start(1, MessagePackage, ?MEASURE_CODECS).
+ do_start(1, ?DEFAULT_OPTS, MessagePackage, ?MEASURE_CODECS).
+
+start(Factor, Opts) when is_integer(Factor) andalso (Factor > 0) andalso
+ is_map(Opts) ->
+ do_start(Factor, Opts, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS).
-do_start(Factor, MessagePackageRaw, Codecs) ->
+do_start(Factor, Opts, MessagePackageRaw, Codecs) ->
MessagePackage = parse_message_package(MessagePackageRaw),
- meas_init(Factor, MessagePackage, Codecs).
+ meas_init(Factor, Opts, MessagePackage, Codecs).
parse_message_package(MessagePackageRaw) when is_list(MessagePackageRaw) ->
list_to_atom(MessagePackageRaw);
@@ -118,7 +124,7 @@ parse_message_package(BadMessagePackage) ->
%% pretty | compact | ber | per | erlang
%%
-meas_init(Factor, MessagePackage, Codecs) ->
+meas_init(Factor, Opts, MessagePackage, Codecs) ->
%% process_flag(trap_exit, true),
io:format("~nRun meas on message package: ~p~n~n", [MessagePackage]),
display_os_info(),
@@ -129,7 +135,7 @@ meas_init(Factor, MessagePackage, Codecs) ->
case megaco_codec_transform:messages(MessagePackage) of
Messages when is_list(Messages) ->
ExpandedMessages = expand_messages(Codecs, Messages),
- Results = t1(Factor, ExpandedMessages, []),
+ Results = t1(Factor, Opts, ExpandedMessages, []),
display_time(Started, os:timestamp()),
store_results(Results);
Error ->
@@ -144,12 +150,8 @@ display_os_info() ->
Str ->
Str
end,
- case os:type() of
- {OsFam, OsName} ->
- io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]);
- OsFam ->
- io:format("OS: ~p: ~s~n", [OsFam, V])
- end.
+ {OsFam, OsName} = os:type(),
+ io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]).
display_system_info() ->
SysArch = string:strip(erlang:system_info(system_architecture),right,$\n),
@@ -163,6 +165,16 @@ display_app_info() ->
display_megaco_info(),
display_asn1_info().
+%% The instruction, nowarn_function, is because I can't figure out
+%% how to suppress the warnings about
+%% megaco_flex_scanner:is_enabled/0 and
+%% megaco_flex_scanner:is_reentrant_enabled/0:
+%%
+%% "The pattern 'false' can never match the type 'true'"
+%%
+%% This is because the result of calling these function(s) is
+%% basically decided at compile time (true or false).
+-dialyzer({nowarn_function, display_megaco_info/0}).
display_megaco_info() ->
MI = megaco:module_info(),
{value, {attributes, Attr}} = lists:keysearch(attributes, 1, MI),
@@ -236,26 +248,26 @@ format_diff(Start, Fin) ->
-t1(_Factor, [], Results) ->
+t1(_Factor, _Opts, [], Results) ->
lists:reverse(Results);
-t1(Factor, [{Id, Codec, Conf, _, _} = ECodec|EMsgs], Results) ->
- case (catch measure(Factor, ECodec)) of
+t1(Factor, Opts, [{Id, Codec, Conf, _, _} = ECodec|EMsgs], Results) ->
+ case (catch measure(Factor, Opts, ECodec)) of
{'EXIT', Reason} ->
error("measure of codec ~p exited: ~n~p", [Codec, Reason]),
- t1(Factor, EMsgs, Results);
+ t1(Factor, Opts, EMsgs, Results);
{error, Reason} ->
error("skipping codec ~p: ~n~p", [Codec, Reason]),
- t1(Factor, EMsgs, Results);
+ t1(Factor, Opts, EMsgs, Results);
{ok, Res} ->
- t1(Factor, EMsgs, [{Id, Conf, Res}| Results])
+ t1(Factor, Opts, EMsgs, [{Id, Conf, Res}| Results])
end.
-measure(Factor, {Id, Codec, Conf, Count, Msgs}) ->
+measure(Factor, Opts, {Id, Codec, Conf, Count, Msgs}) ->
io:format("[~s] measure using codec ~p ~p~n ", [?FTS(), Codec, Conf]),
{Init, Conf1} = measure_init(Conf),
Conf2 = [{version3,?V3}|Conf1],
- Res = measure(Factor, Id, Codec, Conf2, Msgs, [], Count),
+ Res = measure(Factor, Opts, Id, Codec, Conf2, Msgs, [], Count),
measure_fin(Init),
Res.
@@ -303,9 +315,7 @@ expand_codec(Codec) ->
{Codec, megaco_erl_dist_encoder, [compressed], 400},
{Codec, megaco_erl_dist_encoder, [megaco_compressed], 10000},
{Codec, megaco_erl_dist_encoder, [], 10000}
- ];
- Else ->
- exit({error, {invalid_codec, Else}})
+ ]
end.
@@ -322,10 +332,10 @@ measure_fin(_) ->
ok.
-measure(_Factor, _Dir, _Codec, _Conf, [], [], _MCount) ->
+measure(_Factor, _Opts, _Dir, _Codec, _Conf, [], [], _MCount) ->
{error, no_messages};
-measure(_Factor, _Dir, _Codec, _Conf, [], Res, _MCount) ->
+measure(_Factor, _Opts, _Dir, _Codec, _Conf, [], Res, _MCount) ->
Eavg = avg([Etime/Ecnt || #stat{ecount = Ecnt, etime = Etime} <- Res]),
Davg = avg([Dtime/Dcnt || #stat{dcount = Dcnt, dtime = Dtime} <- Res]),
@@ -340,33 +350,41 @@ measure(_Factor, _Dir, _Codec, _Conf, [], Res, _MCount) ->
{ok, lists:reverse(Res)};
-measure(Factor, Dir, Codec, Conf, [{Name, Bin}|Msgs], Results, MCount) ->
- io:format(" ~p", [Name]),
- case (catch do_measure(Factor, Dir, Codec, Conf, Name, Bin, MCount)) of
+measure(Factor, #{verbose := Verbose} = Opts,
+ Dir, Codec, Conf, [{Name, Bin}|Msgs], Results, MCount) ->
+ vprint(Verbose, " ~p", [Name]),
+ case (catch do_measure(Factor, Opts,
+ Dir, Codec, Conf, Name, Bin, MCount)) of
{ok, Stat} ->
- measure(Factor, Dir, Codec, Conf, Msgs, [Stat | Results], MCount);
+ measure(Factor, Opts,
+ Dir, Codec, Conf, Msgs, [Stat | Results], MCount);
{error, S} ->
- io:format("~n[~s] ~s failed: ~n", [?FTS(), Name]),
+ if
+ (Verbose =:= true) ->
+ io:format("~n[~s] ~s failed: ~n", [?FTS(), Name]);
+ true ->
+ io:format("[~s] ~s failed: ~n", [?FTS(), Name])
+ end,
error(S,[]),
- measure(Factor, Dir, Codec, Conf, Msgs, Results, MCount);
+ measure(Factor, Opts, Dir, Codec, Conf, Msgs, Results, MCount);
{info, S} ->
- case get(verbose) of
+ vprint(Verbose, "~n"),
+ case Verbose orelse get(verbose) of
true ->
- io:format("~n", []),
info(S,[]);
_ ->
- io:format("~n~s skipped~n", [Name])
+ io:format("~s skipped~n", [Name])
end,
- measure(Factor, Dir, Codec, Conf, Msgs, Results, MCount)
+ measure(Factor, Opts, Dir, Codec, Conf, Msgs, Results, MCount)
end.
-do_measure(Factor, _Id, Codec, Conf, Name, BinMsg, MCount) ->
+do_measure(Factor, Opts, _Id, Codec, Conf, Name, BinMsg, MCount) ->
%% io:format("~n~s~n", [binary_to_list(BinMsg)]),
- {Version, NewBin} = detect_version(Codec, Conf, BinMsg),
+ {Version, NewBin} = detect_version(Opts, Codec, Conf, BinMsg),
{Msg, Dcnt, Dtime} =
measure_decode(Factor, Codec, Conf, Version, NewBin, MCount),
{_, Ecnt, Etime} =
@@ -377,16 +395,21 @@ do_measure(Factor, _Id, Codec, Conf, Name, BinMsg, MCount) ->
dcount = Dcnt, dtime = Dtime,
size = size(NewBin)}}.
-detect_version(Codec, Conf, Bin) ->
+detect_version(#{verbose := Verbose} = _Opts, Codec, Conf, Bin) ->
case (catch Codec:version_of(Conf, Bin)) of
{ok, V} ->
- io:format("[~w]", [V]),
- {ok, M} = Codec:decode_message(Conf, V, Bin),
+ vprint(Verbose, "[~w]", [V]),
+ {ok, M} = Codec:decode_message(Conf, V, Bin),
{ok, NewBin} = Codec:encode_message(Conf, V, M),
- io:format("[~w]", [size(NewBin)]),
+ vprint(Verbose, "[~w]", [size(NewBin)]),
{V, NewBin};
Error ->
- io:format("~nversion detection failed:~n~p", [Error]),
+ if
+ (Verbose =:= true) ->
+ io:format("~nversion detection failed:~n~p", [Error]);
+ true ->
+ io:format("version detection failed:~n~p", [Error])
+ end,
Error
end.
@@ -416,20 +439,21 @@ measure_codec(Factor, Codec, Func, Conf, Version, Bin, MCount)
is_atom(Func) andalso
is_list(Conf) andalso
is_integer(MCount) andalso (MCount > 0) ->
- Self = self(),
- Pid = spawn_link(?MODULE, do_measure_codec,
- [Factor, Self, Codec, Func, Conf, Version, Bin, MCount]),
+ {Pid, MRef} =
+ spawn_monitor(?MODULE, do_measure_codec,
+ [Factor, Codec, Func, Conf, Version, Bin, MCount]),
receive
- {measure_result, Pid, Func, Res} ->
+ {'DOWN', MRef, process, Pid, {measure_result, Res}} ->
{ok, Res};
- {error, Pid, Error} ->
+ {'DOWN', MRef, process, Pid, {error, Error}} ->
{error, Error};
- Else ->
+ {'DOWN', MRef, process, Pid, Else} ->
{error, {unexpected_result, Else}}
after ?MEASURE_TIMEOUT ->
Info =
case (catch process_info(Pid)) of
I when is_list(I) ->
+ erlang:demonitor(MRef),
exit(Pid, kill),
I;
_ ->
@@ -439,23 +463,17 @@ measure_codec(Factor, Codec, Func, Conf, Version, Bin, MCount)
end.
-do_measure_codec(Factor, Parent, Codec, Func, Conf, Version, Bin, MCount) ->
+do_measure_codec(Factor, Codec, Func, Conf, Version, Bin, MCount) ->
{ok, Count} = measure_warmup(Codec, Func, Conf, Version, Bin, MCount),
Count2 = Count div Factor,
- %% io:format("do_measure_codec(~w, ~w) -> warmed up:"
- %% "~n MCount: ~w"
- %% "~n Count: ~w"
- %% "~n Count2: ~w", [Codec, Func, MCount, Count, Count2]),
Res = timer:tc(?MODULE, do_measure_codec_loop,
[Codec, Func, Conf, Version, Bin, Count2, dummy]),
case Res of
{Time, {ok, M}} ->
- %% io:format("~w ", [Time]),
- Parent ! {measure_result, self(), Func, {M, Count2, Time}};
+ exit({measure_result, {M, Count2, Time}});
{_Time, Error} ->
- Parent ! {error, self(), Error}
- end,
- unlink(Parent). % Make sure Parent don't get our exit signal
+ exit({error, Error})
+ end.
%% This function does more or less what the real measure function
@@ -467,11 +485,17 @@ measure_warmup(Codec, Func, Conf, Version, M, MCount) ->
Res = timer:tc(?MODULE, do_measure_codec_loop,
[Codec, Func, Conf, Version, M, MCount, dummy]),
case Res of
- {Time, {ok, _}} when is_integer(Time) ->
+ {Time, {ok, _}} when is_integer(Time) andalso (Time > 0) ->
%% OK so far, now calculate the count:
- Count = round(?MEASURE_COUNT_TIME/(Time/MCount)),
- %% io:format("~w ", [Count]),
- {ok, Count};
+ %% For some reason we get a 'badarith' on some platforms
+ %% here. Since this is just the warmup we can try-catch.
+ try round(?MEASURE_COUNT_TIME/(Time/MCount)) of
+ Count ->
+ {ok, Count}
+ catch
+ _:_:_ ->
+ {error, {failed_calculated_count, Time, MCount}}
+ end;
{Time, Error} ->
{error, {warmup_failed, Time, Error}}
end.
@@ -666,6 +690,17 @@ flex_scanner_handler(Pid, PortOrPorts) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+vprint(Verbose, F) ->
+ vprint(Verbose, F, []).
+
+vprint(true, F, A) ->
+ io:format(F, A);
+vprint(_, _, _) ->
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
info(F, A) ->
io:format(F ++ "~n", A).