File 2196-Clean-up-measure-1.patch of Package erlang
From 9a1b1d778b53b152c29b9c8b383efd8373275a97 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Fri, 1 Apr 2022 15:56:56 +0200
Subject: [PATCH 06/11] Clean up measure/1
---
lib/stdlib/test/rand_SUITE.erl | 896 +++++++++++++++------------------
1 file changed, 412 insertions(+), 484 deletions(-)
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index a9b546a5e8..d2d729b594 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -1060,11 +1060,13 @@ crypto64_uniform_n(N, State0) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Not a test but measures the time characteristics of the different algorithms
-measure(Config) ->
+measure(Config) when is_list(Config) ->
ct:timetrap({minutes,60}), %% valgrind needs a lot of time
case ct:get_timetrap_info() of
{_,{_,1}} -> % No scaling
- do_measure(Config);
+ Iterations = ?LOOP div 5,
+ Effort = proplists:get_value(measure_effort, Config, 1),
+ do_measure(Iterations * Effort);
{_,{_,Scale}} ->
{skip,{will_not_run_in_scaled_time,Scale}}
end.
@@ -1095,7 +1097,7 @@ measure(Config) ->
St
end).
-do_measure(_Config) ->
+do_measure(Iterations) ->
Algs =
case crypto_support() of
ok ->
@@ -1107,504 +1109,435 @@ do_measure(_Config) ->
ct:pal("~nRNG uniform integer range 10000 performance~n",[]),
[TMarkUniformRange10000,OverheadUniformRange1000|_] =
measure_1(
- fun (_) -> 10000 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, _State) ->
+ Range = 10000,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
_ =
measure_1(
- fun (_) -> 10000 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- State1 = rand:mcg35(State0),
- %% Just a 'rem' with slightly skewed distribution
- case (State1 rem Range) + 1 of
- R when is_integer(R), 0 < R, R =< Range ->
- State1
- end
- end,
- State)
- end,
- mcg35_inline, TMarkUniformRange10000, OverheadUniformRange1000),
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ St1 = rand:mcg35(St0),
+ %% Just a 'rem' with slightly skewed distribution
+ case (St1 rem Range) + 1 of
+ R when is_integer(R), 0 < R, R =< Range ->
+ St1
+ end
+ end
+ end, mcg35_inline, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
_ =
measure_1(
- fun (_) -> 10000 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- State1 = rand:lcg35(State0),
- %% Just a 'rem' with slightly skewed distribution
- case (State1 rem Range) + 1 of
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ St1 = rand:lcg35(St0),
+ %% Just a 'rem' with slightly skewed distribution
+ case (St1 rem Range) + 1 of
R when is_integer(R), 0 < R, R =< Range ->
- State1
+ St1
end
- end,
- State)
+ end
end,
- lcg35_inline, TMarkUniformRange10000, OverheadUniformRange1000),
+ lcg35_inline, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
_ =
measure_1(
- fun (_) -> 10000 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- {V,State1} = rand:exsp_next(State0),
- %% Just a 'rem' with slightly skewed distribution
- case (V rem Range) + 1 of
- R when is_integer(R), 0 < R, R =< Range ->
- State1
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ {V,St1} = rand:exsp_next(St0),
+ %% Just a 'rem' with slightly skewed distribution
+ case (V rem Range) + 1 of
+ X when is_integer(X), 0 < X, X =< Range ->
+ St1
end
- end,
- State)
+ end
end,
- exsp_inline, TMarkUniformRange10000, OverheadUniformRange1000),
+ exsp_inline, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
_ =
measure_1(
- fun (_) -> 10000 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- %% Just a 'rem' with slightly skewed distribution
- case
- erlang:phash2(erlang:unique_integer(), Range)
- of
- R
- when is_integer(R), 0 =< R, R < Range ->
- State0
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ %% Just a 'rem' with slightly skewed distribution
+ case
+ erlang:phash2(erlang:unique_integer(), Range)
+ of
+ X when is_integer(X), 0 =< X, X < Range ->
+ St0
+ end
+ end
end,
- unique_phash2, TMarkUniformRange10000, OverheadUniformRange1000),
+ unique_phash2, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
_ =
measure_1(
- fun (_) -> 10000 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- %% Just a 'rem' with slightly skewed distribution
- case os:system_time(microsecond) rem Range of
- R
- when is_integer(R), 0 =< R, R < Range ->
- State0
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ %% Just a 'rem' with slightly skewed distribution
+ case os:system_time(microsecond) rem Range of
+ R
+ when is_integer(R), 0 =< R, R < Range ->
+ St0
+ end
+ end
end,
- system_time_rem, TMarkUniformRange10000, OverheadUniformRange1000),
+ system_time_rem, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
%%
ct:pal("~nRNG uniform integer 32 bit performance~n",[]),
[TMarkUniform32Bit,OverheadUniform32Bit|_] =
measure_1(
- fun (_) -> 1 bsl 32 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
+ fun (Mod, _State) ->
+ Range = 1 bsl 32,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
end,
- Algs),
+ Algs, Iterations),
_ =
measure_1(
- fun (_) -> 1 bsl 32 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- case rand:lcg35(State0) bsr (35-32) of
- R when is_integer(R), 0 =< R, R < Range ->
- R
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ St1 = rand:lcg35(St0),
+ case St1 bsr (35-32) of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St1
+ end
+ end
end,
- lcg35_inline, TMarkUniform32Bit, OverheadUniform32Bit),
+ lcg35_inline, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
_ =
measure_1(
- fun (_) -> 1 bsl 32 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- {V, State1} = rand:exsp_next(State0),
- case V bsr (58-32) of
- R when is_integer(R), 0 =< R, R < Range ->
- State1
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ {V, St1} = rand:exsp_next(St0),
+ case V bsr (58-32) of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St1
+ end
+ end
end,
- exsp_inline, TMarkUniform32Bit, OverheadUniform32Bit),
+ exsp_inline, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
_ =
measure_1(
- fun (_) -> 1 bsl 32 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- case
- erlang:phash2(erlang:unique_integer(), Range)
- of
- R
- when is_integer(R), 0 =< R, R < Range ->
- State0
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ case
+ erlang:phash2(erlang:unique_integer(), Range)
+ of
+ R
+ when is_integer(R), 0 =< R, R < Range ->
+ St0
+ end
+ end
end,
- unique_phash2, TMarkUniform32Bit, OverheadUniform32Bit),
+ unique_phash2, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
_ =
measure_1(
- fun (_) -> 1 bsl 32 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- case
- os:system_time(microsecond)
- band ((1 bsl 32) - 1)
- of
- R
- when is_integer(R), 0 =< R, R < Range ->
- State0
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ case
+ os:system_time(microsecond)
+ band ((1 bsl 32) - 1)
+ of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St0
+ end
+ end
end,
- system_time_rem, TMarkUniform32Bit, OverheadUniform32Bit),
+ system_time_rem, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
%%
ct:pal("~nRNG uniform integer half range performance~n",[]),
_ =
measure_1(
- fun (State) -> half_range(State) end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
+ fun (Mod, State) ->
+ Range = half_range(State),
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
end,
- Algs),
+ Algs, Iterations),
%%
ct:pal("~nRNG uniform integer half range + 1 performance~n",[]),
_ =
measure_1(
- fun (State) -> half_range(State) + 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = half_range(State) + 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer full range - 1 performance~n",[]),
_ =
measure_1(
- fun (State) -> (half_range(State) bsl 1) - 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = (half_range(State) bsl 1) - 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer full range performance~n",[]),
[TMarkUniformFullRange,OverheadUniformFullRange|_] =
measure_1(
- fun (State) -> half_range(State) bsl 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs ++ [dummy]),
+ fun (Mod, State) ->
+ Range = half_range(State) bsl 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs ++ [dummy], Iterations),
_ =
measure_1(
- fun (_) -> ((1 bsl 35) - 31) - 1 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- case rand:mcg35(State0) of
- R when is_integer(R), 1 =< R, R =< Range ->
- R
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = (1 bsl 35) - 31,
+ fun (St0) ->
+ case rand:mcg35(St0) of
+ R when is_integer(R), 1 =< R, R =< Range ->
+ R
+ end
+ end
end,
- mcg35_inline, TMarkUniformFullRange, OverheadUniformFullRange),
+ mcg35_inline, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
_ =
measure_1(
- fun (_) -> 1 bsl 35 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- case rand:lcg35(State0) of
- R when is_integer(R), 0 =< R, R < Range ->
- R
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 35,
+ fun (St0) ->
+ case rand:lcg35(St0) of
+ R when is_integer(R), 0 =< R, R < Range ->
+ R
+ end
+ end
end,
- lcg35_inline, TMarkUniformFullRange, OverheadUniformFullRange),
+ lcg35_inline, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
_ =
measure_1(
- fun (_) -> 1 bsl 58 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- {V, State1} = rand:exsp_next(State0),
- case V of
- V when is_integer(V), 0 =< V, V < Range ->
- State1
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 58,
+ fun (St0) ->
+ {V, St1} = rand:exsp_next(St0),
+ case V of
+ V when is_integer(V), 0 =< V, V < Range ->
+ St1
+ end
+ end
end,
- exsp_inline, TMarkUniformFullRange, OverheadUniformFullRange),
+ exsp_inline, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
_ =
measure_1(
- fun (_) -> 1 bsl 27 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- case erlang:phash2(erlang:unique_integer()) of
- R
- when is_integer(R), 0 =< R, R < Range ->
- State0
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 27,
+ fun (St0) ->
+ case erlang:phash2(erlang:unique_integer()) of
+ X
+ when is_integer(X), 0 =< X, X < Range ->
+ St0
+ end
+ end
end,
- unique_phash2, TMarkUniformFullRange, OverheadUniformFullRange),
+ unique_phash2, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
_ =
measure_1(
- fun (State) ->
- rand:seed(State),
- half_range(State) bsl 1
+ fun (Mod, _State) ->
+ Range = 1 bsl 27,
+ Generator = fun Mod:uniform/1,
+ fun (St0) ->
+ case Generator(Range) of
+ X when is_integer(X), 1 =< X, X =< Range ->
+ St0
+ end
+ end
end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St) ->
- case Mod:uniform(Range) of
- X when is_integer(X), 1 =< X, X =< Range ->
- St
- end
- end,
- State)
- end,
- procdict, TMarkUniformFullRange, OverheadUniformFullRange),
+ procdict, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
_ =
measure_1(
- fun (State) ->
- _ = put(lcg35_procdict, State),
- 1 bsl 35
- end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0) ->
- case
- put(lcg35_procdict,
- rand:lcg35(get(lcg35_procdict)))
- of
- R when is_integer(R), 0 =< R, R < Range ->
- State0
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 35,
+ fun (St0) ->
+ case
+ put(lcg35_procdict,
+ rand:lcg35(get(lcg35_procdict)))
+ of
+ X when is_integer(X), 0 =< X, X < Range ->
+ St0
+ end
+ end
end,
- lcg35_procdict, TMarkUniformFullRange, OverheadUniformFullRange),
+ lcg35_procdict, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
%%
ct:pal("~nRNG uniform integer full range + 1 performance~n",[]),
_ =
measure_1(
- fun (State) -> (half_range(State) bsl 1) + 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = (half_range(State) bsl 1) + 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer double range performance~n",[]),
_ =
measure_1(
- fun (State) ->
- half_range(State) bsl 2
- end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = half_range(State) bsl 2,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer double range + 1 performance~n",[]),
_ =
measure_1(
- fun (State) ->
- (half_range(State) bsl 2) + 1
- end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = (half_range(State) bsl 2) + 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer 64 bit performance~n",[]),
_ =
measure_1(
- fun (_) -> 1 bsl 64 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, _State) ->
+ Range = 1 bsl 64,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ByteSize = 16, % At about 100 bytes crypto_bytes breaks even to exsss
ct:pal("~nRNG ~w bytes performance~n",[ByteSize]),
_ =
measure_1(
- fun (_) -> ByteSize end,
- fun (State, Size, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_BYTE_SIZE(
- Mod:bytes_s(Size, St0), Size,
- Bin, St1)
- end,
- State)
+ fun (Mod, _State) ->
+ Generator = fun Mod:bytes_s/2,
+ fun (St0) ->
+ ?CHECK_BYTE_SIZE(
+ Generator(ByteSize, St0), ByteSize, Bin, St1)
+ end
end,
case crypto_support() of
ok ->
Algs ++ [crypto_bytes, crypto_bytes_cached];
_ ->
Algs
- end),
+ end, Iterations),
%%
ct:pal("~nRNG uniform float performance~n",[]),
[TMarkUniformFloat,OverheadUniformFloat|_] =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM(Mod:uniform_s(St0), X, St)
- end,
- State)
+ fun (Mod, _State) ->
+ Generator = fun Mod:uniform_s/1,
+ fun (St0) ->
+ ?CHECK_UNIFORM(Generator(St0), X, St)
+ end
end,
- Algs),
+ Algs, Iterations),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, _) ->
- measure_loop(
- fun (State0) ->
- State1 = rand:mcg35(State0),
- %% Too few bits for full mantissa
- case (State1 - 1) * (1/((1 bsl 35) - 31)) of
- R when is_float(R), 0.0 =< R, R < 1.0 ->
- State1
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ fun (St0) ->
+ St1 = rand:mcg35(St0),
+ %% Too few bits for full mantissa
+ case (St1 - 1) * (1/((1 bsl 35) - 31)) of
+ R when is_float(R), 0.0 =< R, R < 1.0 ->
+ St1
+ end
+ end
end,
- mcg35_inline, TMarkUniformFloat, OverheadUniformFloat),
+ mcg35_inline, Iterations,
+ TMarkUniformFloat, OverheadUniformFloat),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, _) ->
- measure_loop(
- fun (State0) ->
- State1 = rand:lcg35(State0),
- %% Too few bits for full mantissa
- case State1 * (1/(1 bsl 35)) of
- R when is_float(R), 0.0 =< R, R < 1.0 ->
- State1
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ fun (St0) ->
+ St1 = rand:lcg35(St0),
+ %% Too few bits for full mantissa
+ case St1 * (1/(1 bsl 35)) of
+ R when is_float(R), 0.0 =< R, R < 1.0 ->
+ St1
+ end
+ end
end,
- lcg35_inline, TMarkUniformFloat, OverheadUniformFloat),
+ lcg35_inline, Iterations,
+ TMarkUniformFloat, OverheadUniformFloat),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, _) ->
- measure_loop(
- fun (State0) ->
- {V,State1} = rand:exsp_next(State0),
- case V * (1/(1 bsl 58)) of
- R when is_float(R), 0.0 =< R, R < 1.0 ->
- State1
- end
- end,
- State)
+ fun (_Mod, _State) ->
+ fun (St0) ->
+ {V,St1} = rand:exsp_next(St0),
+ case V * (1/(1 bsl 58)) of
+ R when is_float(R), 0.0 =< R, R < 1.0 ->
+ St1
+ end
+ end
end,
- exsp_inline, TMarkUniformFloat, OverheadUniformFloat),
+ exsp_inline, Iterations,
+ TMarkUniformFloat, OverheadUniformFloat),
%%
ct:pal("~nRNG uniform_real float performance~n",[]),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM(Mod:uniform_real_s(St0), X, St)
- end,
- State)
+ fun (Mod, _State) ->
+ Generator = fun Mod:uniform_real_s/1,
+ fun (St0) ->
+ ?CHECK_UNIFORM(Generator(St0), X, St)
+ end
end,
- Algs),
+ Algs, Iterations),
%%
ct:pal("~nRNG normal float performance~n",[]),
[TMarkNormalFloat, OverheadNormalFloat|_] =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_NORMAL(Mod:normal_s(St0), X, St1)
- end,
- State)
+ fun (Mod, _State) ->
+ Generator = fun Mod:normal_s/1,
+ fun (St0) ->
+ ?CHECK_NORMAL(Generator(St0), X, St1)
+ end
end,
- Algs),
+ Algs, Iterations),
%% Just for fun try an implementation of the Box-Muller
%% transformation for creating normal distribution floats
%% to compare with our Ziggurat implementation.
@@ -1614,129 +1547,124 @@ do_measure(_Config) ->
TwoPi = 2 * math:pi(),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (State0) ->
- {U1, State1} = Mod:uniform_real_s(State0),
- {U2, State2} = Mod:uniform_s(State1),
- R = math:sqrt(-2.0 * math:log(U1)),
- T = TwoPi * U2,
- Z0 = R * math:cos(T),
- Z1 = R * math:sin(T),
- ?CHECK_NORMAL({Z0 + Z1, State2}, X, State3)
- end,
- State)
+ fun (Mod, _State) ->
+ fun (St0) ->
+ {U1, St1} = Mod:uniform_real_s(St0),
+ {U2, St2} = Mod:uniform_s(St1),
+ R = math:sqrt(-2.0 * math:log(U1)),
+ T = TwoPi * U2,
+ Z0 = R * math:cos(T),
+ Z1 = R * math:sin(T),
+ ?CHECK_NORMAL({Z0 + Z1, St2}, X, St3)
+ end
end,
- exsss, TMarkNormalFloat, OverheadNormalFloat),
+ exsss, Iterations,
+ TMarkNormalFloat, OverheadNormalFloat),
ok.
--define(LOOP_MEASURE, (?LOOP div 5)).
-
-measure_loop(Fun, State) ->
- measure_loop(Fun, State, ?LOOP_MEASURE).
-%%
-measure_loop(Fun, State, N) when 10 =< N ->
+measure_loop(State, Fun, I) when 10 =< I ->
%% Loop unrolling to dilute benchmark overhead...
measure_loop(
- Fun,
Fun(Fun(Fun(Fun(Fun(
Fun(Fun(Fun(Fun(Fun(
State)))))))))),
- N - 10);
-measure_loop(Fun, State, N) when 1 =< N ->
- measure_loop(Fun, Fun(State), N-1);
+ Fun,
+ I - 10);
+measure_loop(State, Fun, I) when 1 =< I ->
+ measure_loop(Fun(State), Fun, I - 1);
measure_loop(_, _, _) ->
ok.
-measure_1(RangeFun, Fun, Algs) ->
- WMark = measure_1(RangeFun, Fun, hd(Algs), warm_up, 0),
+measure_1(InitFun, Algs, Iterations) ->
+ WMark = measure_1(InitFun, hd(Algs), Iterations, warm_up, 0),
Overhead =
measure_1(
- fun (_) -> 1 end,
- fun (State, Range, _) ->
- measure_loop(
- fun (State0)
- when
- is_integer(State0),
- 1 =< State0,
- State0 =< Range ->
- State0
- end,
- State)
- end,
- overhead, WMark, 0),
- TMark = measure_1(RangeFun, Fun, hd(Algs), undefined, Overhead),
+ fun (_Mod, _State) ->
+ Range = 1,
+ fun (St0)
+ when is_integer(St0), 1 =< St0, St0 =< Range ->
+ St0
+ end
+ end, overhead, Iterations, WMark, 0),
+ TMark = measure_1(InitFun, hd(Algs), Iterations, undefined, Overhead),
[TMark,Overhead] ++
- [measure_1(RangeFun, Fun, Alg, TMark, Overhead) || Alg <- tl(Algs)].
+ [measure_1(InitFun, Alg, Iterations, TMark, Overhead)
+ || Alg <- tl(Algs)].
-measure_1(RangeFun, Fun, Alg, TMark, Overhead) ->
+measure_1(InitFun, Alg, Iterations, TMark, Overhead) ->
Parent = self(),
- {Mod, State} =
- case Alg of
- overhead ->
- {?MODULE, 1};
- crypto64 ->
- {rand, crypto64_seed()};
- crypto_cache ->
- {rand, crypto:rand_seed_alg(crypto_cache)};
- crypto ->
- {rand, crypto:rand_seed_s()};
- crypto_aes ->
- {rand,
- crypto:rand_seed_alg(
- crypto_aes, crypto:strong_rand_bytes(256))};
- random ->
- {random, random:seed(os:timestamp()), get(random_seed)};
- crypto_bytes ->
- {?MODULE, ignored_state};
- crypto_bytes_cached ->
- {?MODULE, <<>>};
- unique_phash2 ->
- {?MODULE, ignored_state};
- system_time_rem ->
- {?MODULE, ignored_state};
- mcg35_inline ->
- {_, S} = rand:seed_s(dummy),
- {?MODULE, (S rem ((1 bsl 35)-31 - 1)) + 1};
- lcg35_inline ->
- {_, S} = rand:seed_s(dummy),
- {?MODULE, S bsr (58-35)};
- lcg35_procdict ->
- {_, S} = rand:seed_s(dummy),
- {?MODULE, S bsr (58-35)};
- exsp_inline ->
- {_, S} = rand:seed_s(exsp),
- {?MODULE, S};
- procdict ->
- {rand, rand:seed_s(exsss)};
- _ ->
- {rand, rand:seed_s(Alg)}
+ MeasureFun =
+ fun () ->
+ {Mod, State} = measure_init(Alg),
+ IterFun = InitFun(Mod, State),
+ {T, ok} =
+ timer:tc(
+ fun () ->
+ measure_loop(State, IterFun, Iterations)
+ end),
+ Time = T - Overhead,
+ Percent =
+ case TMark of
+ warm_up -> "(warm-up)";
+ undefined -> " 100.0%";
+ _ ->
+ io_lib:format(
+ "~8.1f%", [(Time * 100 + 50) / TMark])
+ end,
+ io:format(
+ "~.24w: ~8.1f ns ~s~n",
+ [Alg, (Time * 1000 + 500) / Iterations, Percent]),
+ Parent ! {self(), Time},
+ ok
end,
- Pid = spawn_link(
- fun() ->
- Range = RangeFun(State),
- {T, ok} = timer:tc(fun () -> Fun(State, Range, Mod) end),
- Time = T - Overhead,
- Percent =
- case TMark of
- warm_up -> "(warm-up)";
- undefined -> " 100.0%";
- _ ->
- io_lib:format(
- "~8.1f%", [(Time * 100 + 50) / TMark])
- end,
- io:format(
- "~.24w: ~8.1f ns ~s [16#~.16b]~n",
- [Alg, (Time * 1000 + 500) / ?LOOP_MEASURE,
- Percent, Range]),
- Parent ! {self(), Time},
- normal
- end),
+ Pid = spawn_link(MeasureFun),
receive
{Pid, Msg} -> Msg
end.
+measure_init(Alg) ->
+ case Alg of
+ overhead ->
+ {?MODULE, 1};
+ crypto64 ->
+ {rand, crypto64_seed()};
+ crypto_cache ->
+ {rand, crypto:rand_seed_alg(crypto_cache)};
+ crypto ->
+ {rand, crypto:rand_seed_s()};
+ crypto_aes ->
+ {rand,
+ crypto:rand_seed_alg(
+ crypto_aes, crypto:strong_rand_bytes(256))};
+ random ->
+ {random, random:seed(os:timestamp()), get(random_seed)};
+ crypto_bytes ->
+ {?MODULE, undefined};
+ crypto_bytes_cached ->
+ {?MODULE, <<>>};
+ unique_phash2 ->
+ {?MODULE, undefined};
+ system_time_rem ->
+ {?MODULE, undefined};
+ mcg35_inline ->
+ {_, S} = rand:seed_s(dummy),
+ {rand, (S rem ((1 bsl 35)-31 - 1)) + 1};
+ lcg35_inline ->
+ {_, S} = rand:seed_s(dummy),
+ {rand, S bsr (58-35)};
+ lcg35_procdict ->
+ {_, S} = rand:seed_s(dummy),
+ _ = put(Alg, S bsr (58-35)),
+ {rand, undefined};
+ exsp_inline ->
+ {_, S} = rand:seed_s(exsp),
+ {rand, S};
+ procdict ->
+ {rand, rand:seed(exsss)};
+ _ ->
+ {rand, rand:seed_s(Alg)}
+ end.
+
%% Comparison algorithm for rand:bytes_s/2 vs. crypto:strong_rand_bytes/1
bytes_s(N, Cache) when is_binary(Cache) ->
%% crypto_bytes_cached
@@ -1748,7 +1676,7 @@ bytes_s(N, Cache) when is_binary(Cache) ->
<<Part/binary, (crypto:strong_rand_bytes(N * 16))/binary>>,
{Bytes, Rest}
end;
-bytes_s(N, ignored_state = St) ->
+bytes_s(N, undefined = St) ->
%% crypto_bytes
{crypto:strong_rand_bytes(N), St}.
--
2.34.1