aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ssl/test/ssl_dist_bench_SUITE.erl224
1 files changed, 205 insertions, 19 deletions
diff --git a/lib/ssl/test/ssl_dist_bench_SUITE.erl b/lib/ssl/test/ssl_dist_bench_SUITE.erl
index 3c7904cf24..7409b69639 100644
--- a/lib/ssl/test/ssl_dist_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_bench_SUITE.erl
@@ -32,6 +32,8 @@
-export(
[setup/1,
roundtrip/1,
+ throughput_0/1,
+ throughput_64/1,
throughput_1024/1,
throughput_4096/1,
throughput_16384/1,
@@ -55,7 +57,9 @@ groups() ->
{setup, [{repeat, 1}], [setup]},
{roundtrip, [{repeat, 1}], [roundtrip]},
{throughput, [{repeat, 1}],
- [throughput_1024,
+ [throughput_0,
+ throughput_64,
+ throughput_1024,
throughput_4096,
throughput_16384,
throughput_65536,
@@ -247,8 +251,9 @@ setup(A, B, Prefix, HA, HB) ->
[] = ssl_apply(HB, erlang, nodes, []),
{SetupTime, CycleTime} =
ssl_apply(HA, fun () -> setup_runner(A, B, Rounds) end),
- [] = ssl_apply(HA, erlang, nodes, []),
- [] = ssl_apply(HB, erlang, nodes, []),
+ ok = ssl_apply(HB, fun () -> setup_wait_nodedown(A, 10000) end),
+ %% [] = ssl_apply(HA, erlang, nodes, []),
+ %% [] = ssl_apply(HB, erlang, nodes, []),
SetupSpeed = round((Rounds*1000000*1000) / SetupTime),
CycleSpeed = round((Rounds*1000000*1000) / CycleTime),
_ = report(Prefix++" Setup", SetupSpeed, "setups/1000s"),
@@ -275,6 +280,22 @@ setup_loop(A, B, T, N) ->
setup_loop(A, B, Time + T, N - 1)
end.
+setup_wait_nodedown(A, Time) ->
+ ok = net_kernel:monitor_nodes(true),
+ case nodes() of
+ [] ->
+ ok;
+ [A] ->
+ receive
+ {nodedown,A} ->
+ ok;
+ Unexpected ->
+ {error,{unexpected,Unexpected}}
+ after Time ->
+ {error,timeout}
+ end
+ end.
+
%%----------------
%% Roundtrip speed
@@ -334,6 +355,18 @@ roundtrip_client(Pid, Mon, StartTime, N) ->
%%-----------------
%% Throughput speed
+throughput_0(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 500000, 0)
+ end, Config).
+
+throughput_64(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 500000, 64)
+ end, Config).
+
throughput_1024(Config) ->
run_nodepair_test(
fun (A, B, Prefix, HA, HB) ->
@@ -373,45 +406,198 @@ throughput_1048576(Config) ->
throughput(A, B, Prefix, HA, HB, Packets, Size) ->
[] = ssl_apply(HA, erlang, nodes, []),
[] = ssl_apply(HB, erlang, nodes, []),
- Time =
+ #{time := Time,
+ dist_stats := DistStats,
+ client_msacc_stats := ClientMsaccStats,
+ client_prof := ClientProf,
+ server_msacc_stats := ServerMsaccStats,
+ server_prof := ServerProf} =
ssl_apply(HA, fun () -> throughput_runner(A, B, Packets, Size) end),
[B] = ssl_apply(HA, erlang, nodes, []),
[A] = ssl_apply(HB, erlang, nodes, []),
- Speed = round((Packets*Size*1000000) / (1024*Time)),
+ ClientMsaccStats =:= undefined orelse
+ msacc:print(ClientMsaccStats),
+ io:format("DistStats: ~p~n", [DistStats]),
+ Overhead =
+ 50 % Distribution protocol headers (empirical) (TLS+=54)
+ + byte_size(erlang:term_to_binary([0|<<>>])), % Benchmark overhead
+ Bytes = Packets * (Size + Overhead),
+ io:format("~w bytes, ~.4g s~n", [Bytes,Time/1000000]),
+ ClientMsaccStats =:= undefined orelse
+ io:format(
+ "Sender core usage ratio: ~.4g ns/byte~n",
+ [msacc:stats(system_runtime, ClientMsaccStats)*1000/Bytes]),
+ ServerMsaccStats =:= undefined orelse
+ begin
+ io:format(
+ "Receiver core usage ratio: ~.4g ns/byte~n",
+ [msacc:stats(system_runtime, ServerMsaccStats)*1000/Bytes]),
+ msacc:print(ServerMsaccStats)
+ end,
+ io:format("******* ClientProf:~n", []), prof_print(ClientProf),
+ io:format("******* ServerProf:~n", []), prof_print(ServerProf),
+ Speed = round((Bytes * 1000000) / (1024 * Time)),
report(Prefix++" Throughput_"++integer_to_list(Size), Speed, "kB/s").
%% Runs on node A and spawns a server on node B
throughput_runner(A, B, Rounds, Size) ->
Payload = payload(Size),
- ClientPid = self(),
[A] = rpc:call(B, erlang, nodes, []),
+ ClientPid = self(),
ServerPid =
erlang:spawn(
B,
fun () -> throughput_server(ClientPid, Rounds) end),
ServerMon = erlang:monitor(process, ServerPid),
- microseconds(
- throughput_client(
- ServerPid, ServerMon, Payload, start_time(), Rounds)).
+ msacc:available() andalso
+ begin
+ msacc:stop(),
+ msacc:reset(),
+ msacc:start(),
+ ok
+ end,
+ prof_start(),
+ {Time,ServerMsaccStats,ServerProf} =
+ throughput_client(ServerPid, ServerMon, Payload, Rounds),
+ prof_stop(),
+ ClientMsaccStats =
+ case msacc:available() of
+ true ->
+ MStats = msacc:stats(),
+ msacc:stop(),
+ MStats;
+ false ->
+ undefined
+ end,
+ ClientProf = prof_end(),
+ [{_Node,Socket}] = dig_dist_node_sockets(),
+ DistStats = inet:getstat(Socket),
+ #{time => microseconds(Time),
+ dist_stats => DistStats,
+ client_msacc_stats => ClientMsaccStats,
+ client_prof => ClientProf,
+ server_msacc_stats => ServerMsaccStats,
+ server_prof => ServerProf}.
+
+dig_dist_node_sockets() ->
+ [case DistCtrl of
+ {_Node,Socket} = NodeSocket when is_port(Socket) ->
+ NodeSocket;
+ {Node,DistCtrlPid} when is_pid(DistCtrlPid) ->
+ [{links,DistCtrlLinks}] = process_info(DistCtrlPid, [links]),
+ case [S || S <- DistCtrlLinks, is_port(S)] of
+ [Socket] ->
+ {Node,Socket};
+ [] ->
+ [{monitors,[{process,DistSenderPid}]}] =
+ process_info(DistCtrlPid, [monitors]),
+ [{links,DistSenderLinks}] =
+ process_info(DistSenderPid, [links]),
+ [Socket] = [S || S <- DistSenderLinks, is_port(S)],
+ {Node,Socket}
+ end
+ end || DistCtrl <- erlang:system_info(dist_ctrl)].
+
-throughput_server(_Pid, 0) ->
- ok;
throughput_server(Pid, N) ->
+ msacc:available() andalso
+ begin
+ msacc:stop(),
+ msacc:reset(),
+ msacc:start(),
+ ok
+ end,
+ prof_start(),
+ throughput_server_loop(Pid, N).
+
+throughput_server_loop(_Pid, 0) ->
+ prof_stop(),
+ MsaccStats =
+ case msacc:available() of
+ true ->
+ msacc:stop(),
+ MStats = msacc:stats(),
+ msacc:reset(),
+ MStats;
+ false ->
+ undefined
+ end,
+ Prof = prof_end(),
+ exit({ok,MsaccStats,Prof});
+throughput_server_loop(Pid, N) ->
receive
- [N|_] ->
- throughput_server(Pid, N-1)
+ {Pid, N, _} ->
+ throughput_server_loop(Pid, N-1)
end.
-throughput_client(_Pid, Mon, _Payload, StartTime, 0) ->
+throughput_client(Pid, Mon, Payload, N) ->
+ throughput_client_loop(Pid, Mon, Payload, N, start_time()).
+
+throughput_client_loop(_Pid, Mon, _Payload, 0, StartTime) ->
receive
- {'DOWN', Mon, _, _, normal} ->
- elapsed_time(StartTime);
+ {'DOWN', Mon, _, _, {ok,MsaccStats,Prof}} ->
+ {elapsed_time(StartTime),MsaccStats,Prof};
{'DOWN', Mon, _, _, Other} ->
exit(Other)
end;
-throughput_client(Pid, Mon, Payload, StartTime, N) ->
- Pid ! [N|Payload],
- throughput_client(Pid, Mon, Payload, StartTime, N - 1).
+throughput_client_loop(Pid, Mon, Payload, N, StartTime) ->
+ Pid ! {self(), N, Payload},
+ throughput_client_loop(Pid, Mon, Payload, N - 1, StartTime).
+
+
+-define(prof, none). % none | cprof | eprof
+
+-if(?prof =:= cprof).
+prof_start() ->
+ cprof:stop(),
+ cprof:start(),
+ ok.
+-elif(?prof =:= eprof).
+prof_start() ->
+ {ok,_} = eprof:start(),
+ profiling = eprof:start_profiling(processes()),
+ ok.
+-elif(?prof =:= none).
+prof_start() ->
+ ok.
+-endif.
+
+-if(?prof =:= cprof).
+prof_stop() ->
+ cprof:pause(),
+ ok.
+-elif(?prof =:= eprof).
+prof_stop() ->
+ _ = eprof:stop_profiling(),
+ ok.
+-elif(?prof =:= none).
+prof_stop() ->
+ ok.
+-endif.
+
+-if(?prof =:= cprof).
+prof_end() ->
+ Prof = cprof:analyse(),
+ cprof:stop(),
+ Prof.
+-elif(?prof =:= eprof).
+prof_end() ->
+ eprof:dump_data().
+-elif(?prof =:= none).
+prof_end() ->
+ [].
+-endif.
+
+-if(?prof =:= cprof).
+prof_print(Prof) ->
+ io:format("~p.~n", [Prof]).
+-elif(?prof =:= eprof).
+prof_print(Dump) ->
+ eprof:analyze(undefined, total, [], Dump).
+-elif(?prof =:= none).
+prof_print([]) ->
+ ok.
+-endif.
%%%-------------------------------------------------------------------
%%% Test cases helpers