|
|
@ -1,43 +1,29 @@ |
|
|
|
-module(tpCallGrind). |
|
|
|
|
|
|
|
-export([patterns/0]). |
|
|
|
-export([profile/2]). |
|
|
|
-export([profile/3]). |
|
|
|
-export([pts/0]). |
|
|
|
-export([pfs/2]). |
|
|
|
-export([pfm/3]). |
|
|
|
-export([profile_many/2]). |
|
|
|
-export([profile_many/3]). |
|
|
|
|
|
|
|
%% @todo Add an option with a list of modules to exclude. |
|
|
|
|
|
|
|
-type opts() :: #{ |
|
|
|
scope => global | per_process, %% Whether we filter the output per process. |
|
|
|
running => boolean() %% Whether we compute and save wait times. |
|
|
|
scope => global | per_process, %% Whether we filter the output per process. |
|
|
|
running => boolean() %% Whether we compute and save wait times. |
|
|
|
}. |
|
|
|
|
|
|
|
-record(call, { |
|
|
|
%% The MFA for the call. |
|
|
|
mfa :: atom(), |
|
|
|
%% The source file name. |
|
|
|
source :: {string(), pos_integer()}, |
|
|
|
%% The timestamp for the call. |
|
|
|
ts :: pos_integer(), |
|
|
|
%% The timestamp for when we last started executing this function. |
|
|
|
self_ts :: pos_integer(), |
|
|
|
%% Execution time including subcalls. |
|
|
|
incl :: undefined | non_neg_integer(), |
|
|
|
%% Execution time excluding subcalls. |
|
|
|
self = 0 :: integer(), |
|
|
|
%% Number of times the function was called. |
|
|
|
count = 1 :: pos_integer(), |
|
|
|
%% Time when the process was not running in this function. |
|
|
|
wait = 0 :: non_neg_integer(), |
|
|
|
%% Time when the process was not running in this function or any subcalls. |
|
|
|
wait_incl = 0 :: non_neg_integer(), |
|
|
|
%% Number of times the process was scheduled out. |
|
|
|
wait_count = 0 :: non_neg_integer(), |
|
|
|
%% Number of times the function or any subcall was scheduled out. |
|
|
|
wait_count_incl = 0 :: non_neg_integer(), |
|
|
|
%% Calls done by this MFA. |
|
|
|
calls = #{} :: #{atom() => #call{}} |
|
|
|
mfa :: atom(), %% The MFA for the call. |
|
|
|
source :: {string(), pos_integer()}, %% The source file name. |
|
|
|
ts :: pos_integer(), %% The timestamp for the call. |
|
|
|
self_ts :: pos_integer(), %% The timestamp for when we last started executing this function. |
|
|
|
incl :: undefined | non_neg_integer(), %% Execution time including subcalls. |
|
|
|
self = 0 :: integer(), %% Execution time excluding subcalls. |
|
|
|
count = 1 :: pos_integer(), %% Number of times the function was called. |
|
|
|
wait = 0 :: non_neg_integer(), %% Time when the process was not running in this function. |
|
|
|
wait_incl = 0 :: non_neg_integer(), %% Time when the process was not running in this function or any subcalls. |
|
|
|
wait_count = 0 :: non_neg_integer(), %% Number of times the process was scheduled out. |
|
|
|
wait_count_incl = 0 :: non_neg_integer(), %% Number of times the function or any subcall was scheduled out. |
|
|
|
calls = #{} :: #{atom() => #call{}} %% Calls done by this MFA. |
|
|
|
}). |
|
|
|
|
|
|
|
-record(proc, { |
|
|
@ -64,16 +50,16 @@ running => boolean() %% Whether we compute and save wait time |
|
|
|
sources = #{} :: #{mfa() => {string(), pos_integer()}} |
|
|
|
}). |
|
|
|
|
|
|
|
-spec patterns() -> eTpf:input(). |
|
|
|
patterns() -> |
|
|
|
-spec pts() -> eTpf:input(). |
|
|
|
pts() -> |
|
|
|
[{app, kernel}, {app, stdlib}, {app, looking_glass}]. |
|
|
|
|
|
|
|
-spec profile(file:filename_all(), file:filename_all()) -> ok. |
|
|
|
profile(Input, Output) -> |
|
|
|
profile(Input, Output, #{}). |
|
|
|
-spec pfs(file:filename_all(), file:filename_all()) -> ok. |
|
|
|
pfs(Input, Output) -> |
|
|
|
pfm(Input, Output, #{}). |
|
|
|
|
|
|
|
-spec profile(file:filename_all(), file:filename_all(), opts()) -> ok. |
|
|
|
profile(Input, Output, Opts) -> |
|
|
|
-spec pfm(file:filename_all(), file:filename_all(), opts()) -> ok. |
|
|
|
pfm(Input, Output, Opts) -> |
|
|
|
{ok, OutDevice} = file:open(Output, [write]), |
|
|
|
State = #state{input = Input, output = Output, output_device = OutDevice, opts = Opts}, |
|
|
|
write_header(State), |
|
|
|