Parcourir la source

ft: 部分优化调整

master
SisMaker il y a 3 ans
Parent
révision
3369cf72b0
3 fichiers modifiés avec 302 ajouts et 97 suppressions
  1. +37
    -39
      include/eTpf.hrl
  2. +49
    -58
      src/eTpf.erl
  3. +216
    -0
      src/tc/tpTc.erl

+ 37
- 39
include/eTpf.hrl Voir le fichier

@ -1,56 +1,54 @@
%%
-define(IIF(Cond, Then, That), case Cond of true -> Then; _ -> That end).
%% Ignore Msg Hole Name
-define(eTpfHole, '$eTpfHole').
%%
-define(defTcmMap, #{
tcmIsCut => false
, tcmDepth => 5
, tcmListSize => 32
, tcmMapSize => 32
, tcmTupleSize => 32
, tcmBinSize => 128
, tcmBitSize => 128 * 8
, tcmNestStruct => 6
tcmIsCut => false
, tcmDepth => 5
, tcmListSize => 32
, tcmMapSize => 32
, tcmTupleSize => 32
, tcmBinSize => 128
, tcmBitSize => 128 * 8
, tcmNestStruct => 6
}).
-define(eTpfTracerId, eTpfTracerId).
%%
-export_type([input/0, userInput/0, traceOpts/0, tracerOpts/0]).
-type pattern() :: module() | {app, atom()} | {callback, module(), atom()}.
-type scope() :: {scope, [pid() | port() | all | processes | ports |existing | existing_processes | existing_ports |new | new_processes | new_ports]}.
-type input() :: [pattern() | scope()].
-export_type([pidPortSpec/0, flagList/0, pattern/0, traceOpts/0, tracerOpts/0]).
-type userInput() :: pattern() | input().
-type pidPortSpec() :: PidPortSpec :: pid() | port()| all | processes | ports| existing | existing_processes | existing_ports| new | new_processes | new_ports.
-type flagList() :: erlang:trace_flag().
-type pattern() :: module() | {module(), atom(), atom()} | {app, atom()} | {callback, module(), atom()}.
-type traceOpts() :: #{
mode => trace | profile
, tracerId => any()
, send => boolean()
, running => boolean()
, process_dump => boolean() %% trace选项 使`process_dump`, `true`
tracerId => any()
, stackTc => boolean() %% trace选项 使`process_dump`, `true`
}.
-type tracerOpts() :: #{
%% tracer for socket
port => pos_integer()
%% tracer for file
, fDir => string() %%
, fBaseName => string() %% base file name
, fMaxSize => pos_integer() %%
, fMaxMsg => pos_integer() %%
%% tracer for console
%% trace msg term cut cfg
, tcmIsCut => boolean() %% cut trace msg term
, tcmDepth => pos_integer() %% term cut时保留的最大深度
, tcmListSize => pos_integer() %% List term cut时保留的最大数量
, tcmMapSize => pos_integer() %% Map term cut时保留的最大数量
, tcmTupleSize => pos_integer() %% Tuple term cut时保留的最大数量
, tcmBinSize => pos_integer() %% Bin term cut时保留的最大字节数
, tcmBitSize => pos_integer() %% Bits term cut时保留的最大bit数
, tcmNestStruct => pos_integer() %% term cut时保留的最大数量
%% tracer for socket
port => pos_integer()
%% tracer for file
, fDir => string() %%
, fBaseName => string() %% base file name
, fMaxSize => pos_integer() %%
, fMaxMsg => pos_integer() %%
%% tracer for console
%% trace msg term cut cfg
, tcmIsCut => boolean() %% cut trace msg term
, tcmDepth => pos_integer() %% term cut时保留的最大深度
, tcmListSize => pos_integer() %% List term cut时保留的最大数量
, tcmMapSize => pos_integer() %% Map term cut时保留的最大数量
, tcmTupleSize => pos_integer() %% Tuple term cut时保留的最大数量
, tcmBinSize => pos_integer() %% Bin term cut时保留的最大字节数
, tcmBitSize => pos_integer() %% Bits term cut时保留的最大bit数
, tcmNestStruct => pos_integer() %% term cut时保留的最大数量
}.

+ 49
- 58
src/eTpf.erl Voir le fichier

@ -3,8 +3,16 @@
-include("eTpf.hrl").
-export([
%% trace函数
trace/1
, trace/2
, trace/3
, trace/6
, stop/0
, stop/1
%%
sts/0 %% tpTracerShell
, sts/0 %% tpTracerShell
, stl/0 %% tpTracerLog
, stf/0 %% tpTracerFile
@ -30,17 +38,9 @@
, gcPfs/1
, gcPfm/2
%% trace函数
, trace/1
, trace/2
, trace/3
, trace/4
, stop/0
, stop/1
]).
-compile([export_all]).
-compile([export_all, nowarn_export_all]).
sts() ->
trace([{app, eSync}, {scope, [whereis(esSyncSrv)]}]).
@ -106,36 +106,37 @@ gcPfs(InputFile) ->
gcPfm(InputFiles, Cwd) ->
tpGcColl:pfm(InputFiles, Cwd).
-spec trace(userInput()) -> ok.
trace(Input) ->
trace(Input, tpTracerShell).
-spec trace(pidPortSpec()) -> ok.
trace(PidPortSpec) ->
trace(PidPortSpec, tpTracerShell).
-spec trace(userInput(), module()) -> ok.
trace(Input, TracerMod) ->
trace(Input, TracerMod, #{}, #{}).
-spec trace(pidPortSpec(), module()) -> ok.
trace(PidPortSpec, TracerMod) ->
trace(PidPortSpec, TracerMod, #{}).
-spec trace(userInput(), module(), tracerOpts()) -> ok.
trace(Input, TracerMod, TracerOpts) ->
trace(Input, TracerMod, TracerOpts, #{}).
-spec trace(pidPortSpec(), module(), tracerOpts()) -> ok.
trace(PidPortSpec, TracerMod, TracerOpts) ->
trace(PidPortSpec, [all], [{'_', '_', '_'}], TracerMod, TracerOpts, #{}).
-spec trace(userInput(), module(), tracerOpts(), traceOpts()) -> ok.
trace(Input, TracerMod, TracerOpts, TraceOpts) when is_list(Input) ->
InputList = case is_list(Input) of true -> Input; _ -> [Input] end,
doTrace(InputList, TracerMod, TracerOpts, TraceOpts).
-spec trace(pidPortSpec(), flagList(), pattern(), module(), tracerOpts(), traceOpts()) -> ok.
trace(PidPortSpec, FlagList, TraceMods, TracerMod, TracerOpts, TraceOpts) ->
InputList = case is_list(PidPortSpec) of true -> PidPortSpec; _ -> [PidPortSpec] end,
doTrace(InputList, FlagList, TraceMods, TracerMod, TracerOpts, TraceOpts).
doTrace(PidPortSpec, FlagList, TraceMods, TracerMod, TracerOpts, TraceOpts) ->
_ = application:ensure_all_started(eTpf),
TracerId = maps:get(tracerId, TraceOpts, ?eTpfTracerId),
case supervisor:start_child(eTpf_sup, #{
id => TracerId,
start => {TracerMod, start_link, [TracerOpts]},
restart => temporary,
type => worker,
shutdown => infinity
}) of
TracerSpec = #{
id => TracerId
, start => {TracerMod, start_link, [TracerOpts]}
, restart => temporary
, type => worker
, shutdown => infinity
},
case supervisor:start_child(eTpf_sup, TracerSpec) of
{ok, TracerPid} ->
_Mode = maps:get(mode, TraceOpts, trace),
LastTraceMods = flattenMods(TraceMods, []),
traceInput(PidPortSpec, FlagList, LastTraceMods, TracerPid, TraceOpts),
ok;
@ -144,48 +145,38 @@ doTrace(PidPortSpec, FlagList, TraceMods, TracerMod, TracerOpts, TraceOpts) ->
end.
flattenMods([], Acc) ->
case lists:flatten(Acc) of
[] ->
['_'];
AllMods ->
AllMods
end;
AllMFA = lists:flatten(Acc),
?IIF(AllMFA == [], [{'_', '_', '_'}], AllMFA);
flattenMods([{callback, Mod, Fun} | Tail], Acc) when is_atom(Mod), is_atom(Fun) ->
Input = flattenMods(Mod:Fun(), []),
flattenMods(Tail, [Input | Acc]);
flattenMods([{app, App} | Tail], Acc) when is_atom(App) ->
_ = application:load(App),
{ok, Mods} = application:get_key(App, modules),
flattenMods(Tail, [Mods | Acc]);
flattenMods([Input | Tail], Acc) ->
flattenMods(Tail, [Input | Acc]).
traceInput(PidPortSpec, FlagList, TraceMods, TracerState, TraceOpts) ->
MFA = [{OneMod, '_', '_'} || OneMod <- Mods],
flattenMods(Tail, [MFA | Acc]);
flattenMods([{_, _, _} = MFA | Tail], Acc) ->
flattenMods(Tail, [MFA | Acc]);
flattenMods([OneMod | Tail], Acc) ->
flattenMods(Tail, [{OneMod, '_', '_'} | Acc]).
traceInput(PidPortSpec, FlagList, TraceMFAs, TracerState, TraceOpts) ->
% tracer进行跟踪
%% @todo It might be useful to count the number of sends
%% or receives a function does.
%ExtraFlags = [running || maps:get(running, TraceOpts, false)] ++ [send || maps:get(send, TraceOpts, false)],
[
begin
%erlang:trace(PidPortSpec, true, [call, procs, arity, return_to, set_on_spawn, {tracer, tpTracerNif, TracerState} | ExtraFlags])
erlang:trace(OnePidPortSpec, true, [{tracer, tpTracerNif, TracerState} | FlagList])
end || OnePidPortSpec <- PidPortSpec
],
MatchSpec =
case TraceOpts of
#{process_dump := true} ->
[{'_', [], [{message, {process_dump}}]}];
_ ->
true
end,
PtFlags = maps:get(FlagList, TraceOpts, [local]),
MatchSpec = ?IIF(maps:get(stackTc, TraceOpts, false), [{'_', [], [{message, {process_dump}}]}], true),
[
begin
begin
%% The module must be loaded before we attempt to trace it.
_ = code:ensure_loaded(OneTraceMods),
io:format("IMY****************** ~p~n ", [OneTraceMods]),
_ = erlang:trace_pattern({OneTraceMods, '_', '_'}, [{'_', [], [{message, {process_dump}}]}], [local])
end || OneTraceMods <- TraceMods
_ = code:ensure_loaded(M),
io:format("IMY****************** ~p~n ", [OneTraceMFA]),
_ = erlang:trace_pattern(OneTraceMFA, MatchSpec, PtFlags)
end || {M, _F, _A} = OneTraceMFA <- TraceMFAs
],
ok.

+ 216
- 0
src/tc/tpTc.erl Voir le fichier

@ -0,0 +1,216 @@
-module(tpTc).
-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]).

Chargement…
Annuler
Enregistrer