-module(acTc). -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 -> 1000 * 1000 * 1000; microsecond -> 1000 * 1000; millisecond -> 1000; second -> 1 end, TU = case ToUnit of native -> erts_internal:time_unit(); perf_counter -> erts_internal:perf_counter_unit(); nanosecond -> 1000 * 1000 * 1000; microsecond -> 1000 * 1000; 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("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"). 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]).