aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/beam_except.erl12
-rw-r--r--lib/crypto/test/crypto_bench_SUITE.erl63
-rw-r--r--lib/ssh/test/ssh_bench_SUITE.erl48
-rw-r--r--lib/stdlib/doc/src/ets.xml25
4 files changed, 93 insertions, 55 deletions
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl
index 49bfb5606f..26b193a35b 100644
--- a/lib/compiler/src/beam_except.erl
+++ b/lib/compiler/src/beam_except.erl
@@ -79,13 +79,15 @@ translate_1(Ar, I, Is, #st{arity=Arity}=St, [{line,_}=Line|Acc1]=Acc0) ->
no ->
translate(Is, St, [I|Acc0]);
{yes,function_clause,Acc2} ->
- case {Line,St} of
- {{line,Loc},#st{lbl=Fi,loc=Loc}} ->
+ case {Is,Line,St} of
+ {[return|_],{line,Loc},#st{lbl=Fi,loc=Loc}} ->
Instr = {jump,{f,Fi}},
translate(Is, St, [Instr|Acc2]);
- {_,_} ->
- %% This must be "error(function_clause, Args)" in
- %% the Erlang source code or a fun. Don't translate.
+ {_,_,_} ->
+ %% Not a call_only instruction, or not the same
+ %% location information as in in the line instruction
+ %% before the func_info instruction. Not safe
+ %% to translate to a jump.
translate(Is, St, [I|Acc0])
end;
{yes,Instr,Acc2} ->
diff --git a/lib/crypto/test/crypto_bench_SUITE.erl b/lib/crypto/test/crypto_bench_SUITE.erl
index e1fd0a63e5..c66a27f0c8 100644
--- a/lib/crypto/test/crypto_bench_SUITE.erl
+++ b/lib/crypto/test/crypto_bench_SUITE.erl
@@ -33,29 +33,39 @@ suite() -> [%%{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]},
all() ->
[
- {group, ciphers_128}
+ {group, textblock_256}
].
groups() ->
[
- {ciphers_128, [{repeat, 3}], [{group,textblock_256}
+ {textblock_256, [], [
+ {group, ciphers_128},
+ {group, ciphers_256}
+ ]},
+
+ {ciphers_128, [{repeat, 5}], [
+ block,
+ stream
]},
- {textblock_256, [{repeat,2}], [
- block,
- stream
- ]}
+ {ciphers_256, [{repeat, 5}], [
+ block,
+ stream,
+ chacha
+ ]}
].
%%%----------------------------------------------------------------
%%%
-init_per_suite(Config) ->
+init_per_suite(Config0) ->
try crypto:start() of
_ ->
[{_,_,Info}] = crypto:info_lib(),
ct:comment("~s",[Info]),
ct:pal("Crypto version: ~p~n~n~p",[Info,crypto:supports()]),
- [{sec_goal,5} | Config]
+ Config1 = measure_openssl_aes_cbc([128,256], Config0),
+ calibrate([{sec_goal,10} | Config1])
+
catch _:_ ->
{fail, "Crypto did not start"}
end.
@@ -65,15 +75,11 @@ end_per_suite(_Config) ->
%%%----------------------------------------------------------------
%%%
-init_per_group(Group, Config0) ->
- ct:pal("~p(~p,..)",[?FUNCTION_NAME,Group]),
-
- Config = calibrate(Config0),
+init_per_group(Group, Config) ->
case atom_to_list(Group) of
"ciphers_"++KeySizeStr ->
KeySize = list_to_integer(KeySizeStr),
- [{key_size,KeySize}
- | measure_openssl_aes_cbc(KeySize, Config)];
+ [{key_size,KeySize} | Config];
"textblock_"++BlockSizeStr ->
BlockSize = list_to_integer(BlockSizeStr),
@@ -87,45 +93,51 @@ end_per_group(_Group, Config) ->
Config.
-measure_openssl_aes_cbc(KeySize, Config) ->
- BLno_acc = [baseline(aes_cbc, KeySize, false)],
+measure_openssl_aes_cbc(KeySizes, Config) ->
+ BLno_acc = [baseline(aes_cbc, KeySize, false) || KeySize <- KeySizes],
ct:pal("Non-accelerated baseline encryption time [µs/block]:~n~p", [BLno_acc]),
- BLacc = [baseline(aes_cbc, KeySize, true)],
+ BLacc = [baseline(aes_cbc, KeySize, true) || KeySize <- KeySizes],
ct:pal("Possibly accelerated baseline encryption time [µs/block]:~n~p", [BLacc]),
[{acc,BLacc},
{no_acc,BLno_acc} | Config].
calibrate(Config) ->
- Secs = proplists:get_value(sec_goal, Config, 5),
+ Secs = proplists:get_value(sec_goal, Config, 10),
{_,Empty} = data(empty, 0, 0),
- {Ne,Te} = run1(Secs*2000, Empty),
+ {Ne,Te} = run1(Secs*3000, Empty),
+ report(["Overhead"], Te/Ne),
[{overhead,Te/Ne} | Config].
%%%================================================================
%%%
%%%
block(Config) ->
- run_cryptos([aes_cbc, aes_gcm, aes_ccm, chacha20_poly1305],
+ run_cryptos([aes_cbc, aes_gcm, aes_ccm],
Config).
stream(Config) ->
- run_cryptos([aes_ctr, chacha20],
+ run_cryptos([aes_ctr],
+ Config).
+
+chacha(Config) ->
+ run_cryptos([chacha20, chacha20_poly1305],
Config).
+
%%%================================================================
%%%
%%%
run_cryptos(Cryptos, Config) ->
- run_cryptos(Cryptos, 1, Config).
-
-run_cryptos(Cryptos, Factor, Config) ->
KeySize = proplists:get_value(key_size, Config),
BlockSize = proplists:get_value(block_size, Config),
MilliSecGoal = 1000*proplists:get_value(sec_goal,Config),
OverHead = proplists:get_value(overhead, Config, 0),
[try
- Factor*run(Crypto,KeySize,BlockSize,MilliSecGoal) - OverHead
+ TimePerOpBrutto = run(Crypto,KeySize,BlockSize,MilliSecGoal),
+ %% ct:pal("Brutto: ~p Overhead: ~p (~.2f %) Netto: ~p",
+ %% [TimePerOpBrutto, OverHead, 100*OverHead/TimePerOpBrutto,TimePerOpBrutto - OverHead]),
+ TimePerOpBrutto - OverHead
of
TimePerOp -> % µs
%% First, Report speed of encrypting blocks of 1000. [blocks/sec]
@@ -263,6 +275,7 @@ run1(MilliSecGoal, Funs) ->
Pid = spawn(fun() ->
{Fi,Fu,Ff} = Funs,
Ctx0 = Fi(),
+ erlang:garbage_collect(),
T0 = start_time(),
{N,Ctx} = loop(Fu, Ctx0, 0),
T = elapsed_time(T0),
diff --git a/lib/ssh/test/ssh_bench_SUITE.erl b/lib/ssh/test/ssh_bench_SUITE.erl
index 764c52b624..2ac4e5636a 100644
--- a/lib/ssh/test/ssh_bench_SUITE.erl
+++ b/lib/ssh/test/ssh_bench_SUITE.erl
@@ -109,11 +109,10 @@ connect(Config) ->
lists:foreach(
fun(KexAlg) ->
PrefAlgs = preferred_algorithms(KexAlg),
- report([{value, measure_connect(Config,
- [{preferred_algorithms,PrefAlgs}])},
- {suite, ?MODULE},
- {name, mk_name(["Connect erlc erld ",KexAlg," [µs]"])}
- ])
+ TimeMicroSec = measure_connect(Config,
+ [{preferred_algorithms,PrefAlgs}]),
+ report(["Connect erlc erld ",KexAlg," [connects per sec]"],
+ 1000000 / TimeMicroSec)
end, KexAlgs).
@@ -130,7 +129,7 @@ measure_connect(Config, Opts) ->
[begin
{Time, {ok,Pid}} = timer:tc(ssh,connect,["localhost", Port, ConnectOptions]),
ssh:close(Pid),
- Time
+ Time % in µs
end || _ <- lists:seq(1,?Nruns)]).
%%%----------------------------------------------------------------
@@ -178,10 +177,6 @@ gen_data(DataSz) ->
<<Data0/binary, Data1/binary>>.
-%% connect_measure(Port, Cipher, Mac, Data, Options) ->
-%% report([{value, 1},
-%% {suite, ?MODULE},
-%% {name, mk_name(["Transfer 1M bytes ",Cipher,"/",Mac," [µs]"])}]);
connect_measure(Port, Cipher, Mac, Data, Options) ->
AES_GCM = {cipher,
[]},
@@ -220,10 +215,8 @@ connect_measure(Port, Cipher, Mac, Data, Options) ->
ssh:close(C),
Time
end || _ <- lists:seq(1,?Nruns)],
-
- report([{value, median(Times)},
- {suite, ?MODULE},
- {name, mk_name(["Transfer 1M bytes ",Cipher,"/",Mac," [µs]"])}]).
+ report(["Transfer ",Cipher,"/",Mac," [Mbyte per sec]"],
+ 1000000 / median(Times)).
send_wait_acc(C, Ch, Data) ->
ssh_connection:send(C, Ch, Data),
@@ -238,12 +231,6 @@ send_wait_acc(C, Ch, Data) ->
%%%
%%%----------------------------------------------------------------
-mk_name(Name) -> [char(C) || C <- lists:concat(Name)].
-
-char($-) -> $_;
-char(C) -> C.
-
-%%%----------------------------------------------------------------
preferred_algorithms(KexAlg) ->
[{kex, [KexAlg]},
{public_key, ['ssh-rsa']},
@@ -265,11 +252,22 @@ median(Data) when is_list(Data) ->
1 ->
lists:nth(N div 2 + 1, SortedData)
end,
- ct:log("median(~p) = ~p",[SortedData,Median]),
+ ct:pal("median(~p) = ~p",[SortedData,Median]),
Median.
+%%%----------------------------------------------------------------
+report(LabelList, Value) ->
+ Label = report_chars(lists:concat(LabelList)),
+ ct:pal("ct_event:notify ~p: ~p", [Label, Value]),
+ ct_event:notify(
+ #event{name = benchmark_data,
+ data = [{suite, ?MODULE},
+ {name, Label},
+ {value, Value}]}).
+
+report_chars(Cs) ->
+ [case C of
+ $- -> $_;
+ _ -> C
+ end || C <- Cs].
-report(Data) ->
- ct:log("EventData = ~p",[Data]),
- ct_event:notify(#event{name = benchmark_data,
- data = Data}).
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index e67397c6fd..7594514b29 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -188,6 +188,31 @@
is used to keep the table fixated during the entire traversal.</p>
</item>
</list>
+ <note>
+ <p>Even though the access of a single object is always guaranteed to be
+ <seealso marker="#concurrency">atomic and isolated</seealso>, each traversal
+ through a table to find the next key is not done with such guarantees. This is often
+ not a problem, but may cause rare subtle "unexpected" effects if a concurrent
+ process inserts objects during a traversal. For example, consider one
+ process doing</p>
+<pre>
+ets:new(t, [ordered_set, named_table]),
+ets:insert(t, {1}),
+ets:insert(t, {2}),
+ets:insert(t, {3}),
+</pre>
+ <p>A concurrent call to <c>ets:first(t)</c>, done by another
+ process, may then in rare cases return <c>2</c> even though
+ <c>2</c> has never existed in the table ordered as the first key. In
+ the same way, a concurrent call to <c>ets:next(t, 1)</c> may return
+ <c>3</c> even though <c>3</c> never existed in the table
+ ordered directly after <c>1</c>.</p>
+ <p>Effects like this are improbable but possible. The probability will
+ further be reduced (if not vanish) if table option
+ <seealso marker="#new_2_write_concurrency"><c>write_concurrency</c></seealso>
+ is not enabled. This can also only be a potential concern for
+ <c>ordered_set</c> where the traversal order is defined.</p>
+ </note>
</section>
<section>