|
|
@ -0,0 +1,217 @@ |
|
|
|
-module(utTc). |
|
|
|
|
|
|
|
-compile(inline). |
|
|
|
-compile({inline_size, 128}). |
|
|
|
|
|
|
|
-export([ |
|
|
|
tc/1 |
|
|
|
, tc/2 |
|
|
|
, tc/3 |
|
|
|
, ts/4 |
|
|
|
, tm/5 |
|
|
|
, cvrTimeUnit/3 |
|
|
|
, test/1 |
|
|
|
]). |
|
|
|
|
|
|
|
%% Measure the execution time (in nanoseconds) for Fun(). |
|
|
|
-spec tc(Fun :: function()) -> {Time :: integer(), Value :: term()}. |
|
|
|
tc(F) -> |
|
|
|
T1 = erlang:monotonic_time(), |
|
|
|
Val = F(), |
|
|
|
T2 = erlang:monotonic_time(), |
|
|
|
Time = cvrTimeUnit(T2 - T1, native, nanosecond), |
|
|
|
{Time, Val}. |
|
|
|
|
|
|
|
%% Measure the execution time (in nanoseconds) for Fun(Args). |
|
|
|
-spec tc(Fun :: function(), Arguments :: [term()]) -> {Time :: integer(), Value :: term()}. |
|
|
|
tc(F, A) -> |
|
|
|
T1 = erlang:monotonic_time(), |
|
|
|
Val = apply(F, A), |
|
|
|
T2 = erlang:monotonic_time(), |
|
|
|
Time = cvrTimeUnit(T2 - T1, native, nanosecond), |
|
|
|
{Time, Val}. |
|
|
|
|
|
|
|
%% Measure the execution time (in nanoseconds) for an MFA. |
|
|
|
-spec tc(Module :: module(), Function :: atom(), Arguments :: [term()]) -> {Time :: integer(), Value :: term()}. |
|
|
|
tc(M, F, A) -> |
|
|
|
T1 = erlang:monotonic_time(), |
|
|
|
Val = apply(M, F, A), |
|
|
|
T2 = erlang:monotonic_time(), |
|
|
|
Time = cvrTimeUnit(T2 - T1, native, nanosecond), |
|
|
|
{Time, Val}. |
|
|
|
|
|
|
|
-spec cvrTimeUnit(Time :: integer(), FromUnit :: erlang:time_unit(), ToUnit :: erlang:time_unit()) -> ConvertedTime :: integer(). |
|
|
|
cvrTimeUnit(Time, FromUnit, ToUnit) -> |
|
|
|
try |
|
|
|
FU = |
|
|
|
case FromUnit of |
|
|
|
native -> erts_internal:time_unit(); |
|
|
|
perf_counter -> erts_internal:perf_counter_unit(); |
|
|
|
nanosecond -> 1000000000; |
|
|
|
microsecond -> 1000000; |
|
|
|
millisecond -> 1000; |
|
|
|
second -> 1 |
|
|
|
end, |
|
|
|
TU = |
|
|
|
case ToUnit of |
|
|
|
native -> erts_internal:time_unit(); |
|
|
|
perf_counter -> erts_internal:perf_counter_unit(); |
|
|
|
nanosecond -> 1000000000; |
|
|
|
microsecond -> 1000000; |
|
|
|
millisecond -> 1000; |
|
|
|
second -> 1 |
|
|
|
end, |
|
|
|
case Time < 0 of |
|
|
|
true -> (TU * Time - (FU - 1)) div FU; |
|
|
|
_ -> TU * Time div FU |
|
|
|
end |
|
|
|
catch |
|
|
|
_ : _ -> |
|
|
|
erlang:error(badarg, [Time, FromUnit, ToUnit]) |
|
|
|
end. |
|
|
|
|
|
|
|
%% 单进程循环测试:LoopTimes是循环次数 |
|
|
|
%% utTc:ts(LoopTimes, Module, Function, ArgsList). |
|
|
|
%% 多进程并发测试:SpawnProcessesCount是并发的进程数 LoopTimes是循环次数 |
|
|
|
%% utTc:tm(ProcessesCount, LoopTimes, Module, Function, ArgsList). |
|
|
|
|
|
|
|
doTc(M, F, A) -> |
|
|
|
T1 = erlang:monotonic_time(), |
|
|
|
apply(M, F, A), |
|
|
|
T2 = erlang:monotonic_time(), |
|
|
|
cvrTimeUnit(T2 - T1, native, nanosecond). |
|
|
|
|
|
|
|
distribution(List, Aver) -> |
|
|
|
distribution(List, Aver, 0, 0). |
|
|
|
distribution([H | T], Aver, Greater, Less) -> |
|
|
|
case H > Aver of |
|
|
|
true -> |
|
|
|
distribution(T, Aver, Greater + 1, Less); |
|
|
|
false -> |
|
|
|
distribution(T, Aver, Greater, Less + 1) |
|
|
|
end; |
|
|
|
distribution([], _Aver, Greater, Less) -> |
|
|
|
{Greater, Less}. |
|
|
|
|
|
|
|
%% =================================================================== |
|
|
|
%% test: one process test N times |
|
|
|
%% =================================================================== |
|
|
|
ts(LoopTime, M, F, A) -> |
|
|
|
{Max, Min, Sum, Aver, Greater, Less} = loopTs(LoopTime, M, F, A, LoopTime, 0, 0, 0, []), |
|
|
|
io:format("=====================~n"), |
|
|
|
io:format("execute Args:~p~n", [A]), |
|
|
|
io:format("execute Fun :~p~n", [F]), |
|
|
|
io:format("execute Mod :~p~n", [M]), |
|
|
|
io:format("execute LoopTime:~p~n", [LoopTime]), |
|
|
|
io:format("MaxTime: ~10s(ns) ~10s(s)~n", [integer_to_binary(Max), float_to_binary(Max / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("MinTime: ~10s(ns) ~10s(s)~n", [integer_to_binary(Min), float_to_binary(Min / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("SumTime: ~10s(ns) ~10s(s)~n", [integer_to_binary(Sum), float_to_binary(Sum / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("AvgTime: ~10s(ns) ~10s(s)~n", [float_to_binary(Aver, [{decimals, 6}, compact]), float_to_binary(Aver / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("Grar : ~10s(cn) ~10s(~s)~n", [integer_to_binary(Greater), float_to_binary(Greater / LoopTime, [{decimals, 2}]), <<"%">>]), |
|
|
|
io:format("Less : ~10s(cn) ~10s(~s)~n", [integer_to_binary(Less), float_to_binary(Less / LoopTime, [{decimals, 2}]), <<"%">>]), |
|
|
|
io:format("=====================~n"). |
|
|
|
|
|
|
|
|
|
|
|
loopTs(0, _M, _F, _A, LoopTime, Max, Min, Sum, List) -> |
|
|
|
Aver = Sum / LoopTime, |
|
|
|
{Greater, Less} = distribution(List, Aver), |
|
|
|
{Max, Min, Sum, Aver, Greater, Less}; |
|
|
|
loopTs(Index, M, F, A, LoopTime, Max, Min, Sum, List) -> |
|
|
|
Nanosecond = doTc(M, F, A), |
|
|
|
NewSum = Sum + Nanosecond, |
|
|
|
if |
|
|
|
Max == 0 -> |
|
|
|
NewMax = NewMin = Nanosecond; |
|
|
|
Max < Nanosecond -> |
|
|
|
NewMax = Nanosecond, |
|
|
|
NewMin = Min; |
|
|
|
Min > Nanosecond -> |
|
|
|
NewMax = Max, |
|
|
|
NewMin = Nanosecond; |
|
|
|
true -> |
|
|
|
NewMax = Max, |
|
|
|
NewMin = Min |
|
|
|
end, |
|
|
|
loopTs(Index - 1, M, F, A, LoopTime, NewMax, NewMin, NewSum, [Nanosecond | List]). |
|
|
|
|
|
|
|
|
|
|
|
%% =================================================================== |
|
|
|
%% Concurrency test: N processes each test one time |
|
|
|
%% =================================================================== |
|
|
|
|
|
|
|
tm(ProcCnt, LoopTime, M, F, A) -> |
|
|
|
loopSpawn(ProcCnt, M, F, A, self(), LoopTime), |
|
|
|
{Max, Min, Sum, Aver, Greater, Less} = collector(ProcCnt, 0, 0, 0, ProcCnt, []), |
|
|
|
io:format("=====================~n"), |
|
|
|
io:format("execute Args:~p~n", [A]), |
|
|
|
io:format("execute Fun :~p~n", [F]), |
|
|
|
io:format("execute Mod :~p~n", [M]), |
|
|
|
io:format("execute LoopTime:~p~n", [LoopTime]), |
|
|
|
io:format("execute ProcCnts:~p~n", [ProcCnt]), |
|
|
|
io:format("PMaxTime: ~10s(ns) ~10s(s)~n", [integer_to_binary(Max), float_to_binary(Max / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("PMinTime: ~10s(ns) ~10s(s)~n", [integer_to_binary(Min), float_to_binary(Min / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("PSumTime: ~10s(ns) ~10s(s)~n", [integer_to_binary(Sum), float_to_binary(Sum / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("PAvgTime: ~10s(ns) ~10s(s)~n", [float_to_binary(Aver, [{decimals, 6}, compact]), float_to_binary(Aver / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("FAvgTime: ~10s(ns) ~10s(s)~n", [float_to_binary(Aver / LoopTime, [{decimals, 6}, compact]), float_to_binary(Aver / LoopTime / 1000000000, [{decimals, 6}, compact])]), |
|
|
|
io:format("PGrar : ~10s(cn) ~10s(~s)~n", [integer_to_binary(Greater), float_to_binary(Greater / ProcCnt, [{decimals, 2}]), <<"%">>]), |
|
|
|
io:format("PLess : ~10s(cn) ~10s(~s)~n", [integer_to_binary(Less), float_to_binary(Less / ProcCnt, [{decimals, 2}]), <<"%">>]), |
|
|
|
io:format("=====================~n"). |
|
|
|
|
|
|
|
|
|
|
|
loopSpawn(0, _, _, _, _, _) -> |
|
|
|
ok; |
|
|
|
loopSpawn(ProcCnt, M, F, A, CollectorPid, LoopTime) -> |
|
|
|
spawn_link(fun() -> worker(LoopTime, M, F, A, CollectorPid) end), |
|
|
|
loopSpawn(ProcCnt - 1, M, F, A, CollectorPid, LoopTime). |
|
|
|
|
|
|
|
collector(0, Max, Min, Sum, ProcCnt, List) -> |
|
|
|
Aver = Sum / ProcCnt, |
|
|
|
{Greater, Less} = distribution(List, Aver), |
|
|
|
{Max, Min, Sum, Aver, Greater, Less}; |
|
|
|
collector(Index, Max, Min, Sum, ProcCnt, List) -> |
|
|
|
receive |
|
|
|
{result, Nanosecond} -> |
|
|
|
NewSum = Sum + Nanosecond, |
|
|
|
if |
|
|
|
Max == 0 -> |
|
|
|
NewMax = NewMin = Nanosecond; |
|
|
|
Max < Nanosecond -> |
|
|
|
NewMax = Nanosecond, |
|
|
|
NewMin = Min; |
|
|
|
Min > Nanosecond -> |
|
|
|
NewMax = Max, |
|
|
|
NewMin = Nanosecond; |
|
|
|
true -> |
|
|
|
NewMax = Max, |
|
|
|
NewMin = Min |
|
|
|
end, |
|
|
|
collector(Index - 1, NewMax, NewMin, NewSum, ProcCnt, [Nanosecond | List]) |
|
|
|
after 1800000 -> |
|
|
|
io:format("execute time out~n"), |
|
|
|
ok |
|
|
|
end. |
|
|
|
|
|
|
|
worker(LoopTime, M, F, A, CollectorPid) -> |
|
|
|
SumTime = loopTm(LoopTime, M, F, A, 0), |
|
|
|
CollectorPid ! {result, SumTime}. |
|
|
|
|
|
|
|
loopTm(0, _, _, _, SumTime) -> |
|
|
|
SumTime; |
|
|
|
loopTm(LoopTime, M, F, A, SumTime) -> |
|
|
|
Microsecond = doTc(M, F, A), |
|
|
|
loopTm(LoopTime - 1, M, F, A, SumTime + Microsecond). |
|
|
|
|
|
|
|
test(N) -> |
|
|
|
M1 = erlang:monotonic_time(), |
|
|
|
timer:sleep(N), |
|
|
|
M2 = erlang:monotonic_time(), |
|
|
|
Time = cvrTimeUnit(M2 - M1, native, nanosecond), |
|
|
|
io:format("IMY******************111 ~p~n", [Time]), |
|
|
|
|
|
|
|
S1 = erlang:system_time(nanosecond), |
|
|
|
timer:sleep(N), |
|
|
|
S2 = erlang:system_time(nanosecond), |
|
|
|
io:format("IMY******************222 ~p~n", [S2 - S1]). |
|
|
|
|
|
|
|
|
|
|
|
|