查看源代码 cprof (工具 v4.1.1)
一个简单的调用计数分析工具,使用断点以尽量减少运行时性能影响。
cprof
模块用于分析程序,找出不同函数被调用的次数。为了尽量减少运行时性能影响,使用了包含计数器的断点。
由于使用了断点,因此无需对要分析的模块进行特殊编译。这些断点只能设置在 BEAM 代码上,因此 BIF 无法进行调用计数跟踪。
调用计数器的大小是主机字长。暂停计数器时使用一位,因此 32 位主机的最大计数器值为 2,147,483,647。
分析结果以包含排序的条目列表的形式提供,每个模块一个条目。每个模块条目包含排序的函数列表。两种情况下的排序顺序都是按调用计数递减排列。
与诸如 eprof
或 fprof
等其他形式的跟踪相比,调用计数跟踪是轻量级的,因为它不需要生成跟踪消息。一些测量表明,性能下降约为 10%。
有关更多信息和一些示例,请参阅 cprof
用户指南。
摘要
函数
等效于 analyse(1)
。
为一个或多个模块收集调用计数器。
收集并分析模块 Module
的所有调用计数器。
暂停所有模块中所有函数的调用计数跟踪,并停止加载模块中所有函数的调用计数跟踪。
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 pause(FuncSpec, '_', '_')
。
暂停匹配模块中匹配函数的调用计数器。
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 restart(FuncSpec, '_', '_')
。
重新启动正在进行调用计数跟踪的匹配模块中匹配函数的调用计数器。
开始所有模块中所有函数的调用计数跟踪,以及加载模块中所有函数的调用计数跟踪。
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 start(FuncSpec, '_', '_')
。
开始匹配模块中匹配函数的调用计数跟踪。
停止所有模块中所有函数的调用计数跟踪,以及加载模块中所有函数的调用计数跟踪。
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 stop(FuncSpec, '_', '_')
。
停止匹配模块中匹配函数的调用计数跟踪。
类型
-type func_analysis_list() :: [{mfa(), FuncCallCount :: non_neg_integer()}].
-type mod_analysis() :: {Mod :: module(), ModCallCount :: non_neg_integer(), FuncAnalysisList :: func_analysis_list()}.
-type mod_analysis_list() :: [mod_analysis()].
函数
-spec analyse() -> {AllCallCount :: non_neg_integer(), ModAnalysisList :: mod_analysis_list()}.
等效于 analyse(1)
。
-spec analyse(Limit) -> {AllCallCount :: non_neg_integer(), ModAnalysisList :: mod_analysis_list()} when Limit :: non_neg_integer(); (Mod) -> ModAnalysis :: mod_analysis() when Mod :: module().
为一个或多个模块收集调用计数器。
如果 ModLimit
是一个模块名称(一个原子),则此调用等效于 analyse(ModLimit, 1)
。
如果 ModLimit
是一个整数,则此函数为每个当前加载的 Module
(除了 cprof
模块本身)调用 analyse(Module, ModLimit)
。这些调用的结果将在一个列表中返回。
-spec analyse(Mod, Limit) -> ModAnalysis :: mod_analysis() when Mod :: module(), Limit :: non_neg_integer().
收集并分析模块 Module
的所有调用计数器。
此函数返回
{Module, ModuleCount, FuncAnalysisList}
其中 FuncAnalysisList
是一个元组列表,每个函数一个元组
{{Module, FunctionName, Arity}, FuncCallCount}
如果在执行 analyse/0,1,2
时调用计数器仍在运行,则结果可能不一致。如果执行 analyse/0,1,2
的进程被调度出去,以便其他进程可以递增正在分析的计数器,则会发生这种情况。在分析之前调用 pause()
可以解决该问题。
所有 FuncCallCount
低于 Limit
的函数都将从 FuncAnalysisList
中排除。但是,它们仍然包含在 ModCallCount
中。
-spec pause() -> non_neg_integer().
暂停所有模块中所有函数的调用计数跟踪,并停止加载模块中所有函数的调用计数跟踪。
-spec pause(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 pause(FuncSpec, '_', '_')
。
如果 FuncSpec
是一个 MFA 元组,{Module, Name, Arity}
,则此调用等效于 pause(Module, Name, Arity)
。
如果 FuncSpec
是元组 {FS}
,则 FS
是 erlang:trace_pattern/3
的第一个参数。例如,如果 FuncSpec
是 {on_load}
,则将暂停加载模块中所有函数的调用计数器。
-spec pause(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().
-spec pause(Mod, Func, Arity) -> non_neg_integer() when Mod :: module(), Func :: atom(), Arity :: arity().
暂停匹配模块中匹配函数的调用计数器。
所有具有调用计数断点的匹配函数的调用计数器都会在其当前计数处暂停。
返回可以具有调用计数断点的匹配函数数量,与使用相同参数的 start/*
返回的数量相同。
-spec restart() -> non_neg_integer().
-spec restart(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 restart(FuncSpec, '_', '_')
。
如果 FuncSpec
是一个 MFA 元组,{Module, Name, Arity}
,则此调用等效于 restart(Module, Name, Arity)
。
如果 FuncSpec
是元组 {FS}
,则 FS
是 erlang:trace_pattern/3
的第一个参数。例如,如果 FuncSpec
是 {on_load}
,则加载模块中所有函数的调用计数器都将设置为零并开始运行。
-spec restart(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().
-spec restart(Mod, Func, Arity) -> non_neg_integer() when Mod :: module(), Func :: atom(), Arity :: arity().
重新启动正在进行调用计数跟踪的匹配模块中匹配函数的调用计数器。
所有具有调用计数断点的匹配函数的调用计数器都设置为零并开始运行。
返回可以具有调用计数断点的匹配函数数量,与使用相同参数的 start/*
返回的数量相同。
-spec start() -> non_neg_integer().
开始所有模块中所有函数的调用计数跟踪,以及加载模块中所有函数的调用计数跟踪。
-spec start(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 start(FuncSpec, '_', '_')
。
如果 FuncSpec
是一个 MFA 元组,{Module, Name, Arity}
,则此调用等效于 start(Module, Name, Arity)
。
如果 FuncSpec
是元组 {FS}
,则 FS
是 erlang:trace_pattern/3
的第一个参数。例如,如果 FuncSpec
是 {on_load}
,则加载模块中所有函数的调用计数器都将设置为零并开始运行。
-spec start(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().
-spec start(Mod, Func, Arity) -> non_neg_integer() when Mod :: module(), Func :: atom(), Arity :: arity().
开始匹配模块中匹配函数的调用计数跟踪。
在没有调用计数断点的匹配函数上设置调用计数断点。所有匹配函数的调用计数器都设置为零并开始运行。
返回具有调用计数断点的匹配函数数量。
-spec stop() -> non_neg_integer().
停止所有模块中所有函数的调用计数跟踪,以及加载模块中所有函数的调用计数跟踪。
-spec stop(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.
如果 FuncSpec
是一个原子,则假定它是一个模块名称,并且此调用等效于 stop(FuncSpec, '_', '_')
。
如果 FuncSpec
是一个 MFA 元组,{Module, Name, Arity}
,则此调用等效于 stop(Module, Name, Arity)
。
如果 FuncSpec
是元组 {FS}
,则 FS
是 erlang:trace_pattern/3
的第一个参数。例如,如果 FuncSpec
是 {on_load}
,则加载模块中所有函数的调用计数器都将被禁用。
-spec stop(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().
等效于 stop(Mod, Func, '_')
。
-spec stop(Mod, Func, Arity) -> non_neg_integer() when Mod :: module(), Func :: atom(), Arity :: arity().
停止匹配模块中匹配函数的调用计数跟踪。
从具有调用计数断点的匹配函数中删除调用计数断点。
返回可以具有调用计数断点的匹配函数数量,该数量与使用相同参数的 start/*
返回的数量相同。