tools

v4.1.4

cprof

A simple Call Count Profiling Tool using breakpoints for minimal runtime performance impact.

The cprof module is used to profile a program to find out how many times different functions are called. To minimize runtime performance impact, breakpoints containing counters are used.

Since breakpoints are used there is no need for special compilation of the modules to be profiled. These breakpoints can only be set on BEAM code, so BIFs cannot be call-count traced.

The size of the call counters is the host machine word size. One bit is used when pausing the counter, so the maximum counter value for a 32-bit host is 2,147,483,647.

The profiling result is delivered as a term containing a sorted list of entries, one per module. Each module entry contains a sorted list of functions. The sorting order in both cases is of decreasing call count.

Call count tracing is lightweight compared to other forms of tracing, such as eprof or fprof, since no trace messages have to be generated. Some measurements indicates that the performance degradation is about 10 percent.

For more information and some examples, see the User's Guide for cprof.

Summary

Types

func_analysis_list()

mod_analysis()

mod_analysis_list()

Functions

analyse()

Equivalent to analyse(1).

analyse(ModLimit)

Collect call counters for one or more modules.

analyse(Module, Limit)

Collects and analyses all call counters for module Module.

pause()

Pause call count tracing for all functions in all modules and stop it for all functions in modules to be loaded.

pause(FuncSpec)

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to pause(FuncSpec, '_', '_').

pause(Mod, Func)

Equivalent to pause(Mod, Func, '_').

pause(Mod, Func, Arity)

Pause call counters for matching functions in matching modules.

restart()

Equivalent to restart('_', '_', '_').

restart(FuncSpec)

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to restart(FuncSpec, '_', '_').

restart(Mod, Func)

Equivalent to restart(Mod, Func, '_').

restart(Mod, Func, Arity)

Restart call counters for the matching functions in matching modules that are call-count traced.

start()

Start call count tracing for all functions in all modules, and also for all functions in modules to be loaded.

start(FuncSpec)

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to start(FuncSpec, '_', '_').

start(Mod, Func)

Equivalent to start(Mod, Func, '_').

start(Mod, Func, Arity)

Start call count tracing for matching functions in matching modules.

stop()

Stop call count tracing for all functions in all modules, and also for all functions in modules to be loaded.

stop(FuncSpec)

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to stop(FuncSpec, '_', '_').

stop(Mod, Func)

Equivalent to stop(Mod, Func, '_').

stop(Mod, Func, Arity)

Stop call count tracing for matching functions in matching modules.

Types

func_analysis_list()

(not exported)

-type func_analysis_list() :: [{mfa(), FuncCallCount :: non_neg_integer()}].

mod_analysis()

(not exported)

-type mod_analysis() ::
          {Mod :: module(), ModCallCount :: non_neg_integer(), FuncAnalysisList :: func_analysis_list()}.

mod_analysis_list()

(not exported)

-type mod_analysis_list() :: [mod_analysis()].

Functions

analyse()

-spec analyse() -> {AllCallCount :: non_neg_integer(), ModAnalysisList :: mod_analysis_list()}.

Equivalent to analyse(1).

analyse(ModLimit)

-spec analyse(Limit) -> {AllCallCount :: non_neg_integer(), ModAnalysisList :: mod_analysis_list()}
                 when Limit :: non_neg_integer();
             (Mod) -> ModAnalysis :: mod_analysis() when Mod :: module().

Collect call counters for one or more modules.

If ModLimit is a module name (an atom), this call is equivalent to analyse(ModLimit, 1).

If ModLimit is an integer, this function calls analyse(Module, ModLimit) for each Module that is currently loaded (except the cprof module itself). The result from those calls are returned in a list.

analyse(Module, Limit)

-spec analyse(Mod, Limit) -> ModAnalysis :: mod_analysis()
                 when Mod :: module(), Limit :: non_neg_integer().

Collects and analyses all call counters for module Module.

This function returns:

{Module, ModuleCount, FuncAnalysisList}

where FuncAnalysisList is a list of tuples, one for each function:

{{Module, FunctionName, Arity}, FuncCallCount}

If call counters are still running while analyse/0,1,2 is executing, the result could be inconsistent. This happens if the process executing analyse/0,1,2 is scheduled out so some other process can increment the counters that are being analysed. Calling pause() before analysing takes care of that problem.

All functions with a FuncCallCount lower than Limit are excluded from FuncAnalysisList. They are still included in ModCallCount, though.

pause()

-spec pause() -> non_neg_integer().

Pause call count tracing for all functions in all modules and stop it for all functions in modules to be loaded.

This call is equivalent to pause('_', '_', '_') + stop({on_load}).

pause(FuncSpec)

-spec pause(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to pause(FuncSpec, '_', '_').

If FuncSpec is an MFA tuple, {Module, Name, Arity}, this call is equivalent to pause(Module, Name, Arity).

If FuncSpec is tuple {FS}, FS is the first argument to erlang:trace_pattern/3. For example, if FuncSpec is {on_load}, call counters will be paused for all functions in modules to be loaded.

pause(Mod, Func)

-spec pause(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().

Equivalent to pause(Mod, Func, '_').

pause(Mod, Func, Arity)

-spec pause(Mod, Func, Arity) -> non_neg_integer()
               when Mod :: module(), Func :: atom(), Arity :: arity().

Pause call counters for matching functions in matching modules.

The call counters for all matching functions that have call count breakpoints are paused at their current count.

Return the number of matching functions that can have call count breakpoints, the same as start/* with the same arguments would have returned.

restart()

-spec restart() -> non_neg_integer().

Equivalent to restart('_', '_', '_').

restart(FuncSpec)

-spec restart(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to restart(FuncSpec, '_', '_').

If FuncSpec is an MFA tuple, {Module, Name, Arity}, this call is equivalent to restart(Module, Name, Arity).

If FuncSpec is tuple {FS}, FS is the first argument to erlang:trace_pattern/3. For example, if FuncSpec is {on_load}, call counters will be set to zero and running for all functions in modules to be loaded.

restart(Mod, Func)

-spec restart(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().

Equivalent to restart(Mod, Func, '_').

restart(Mod, Func, Arity)

-spec restart(Mod, Func, Arity) -> non_neg_integer()
                 when Mod :: module(), Func :: atom(), Arity :: arity().

Restart call counters for the matching functions in matching modules that are call-count traced.

The call counters for all matching functions that has call count breakpoints are set to zero and running.

Return the number of matching functions that can have call count breakpoints, the same as start/* with the same arguments would have returned.

start()

-spec start() -> non_neg_integer().

Start call count tracing for all functions in all modules, and also for all functions in modules to be loaded.

This is equivalent to start('_', '_', '_') + start({on_load}).

start(FuncSpec)

-spec start(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to start(FuncSpec, '_', '_').

If FuncSpec is an MFA tuple, {Module, Name, Arity}, this call is equivalent to start(Module, Name, Arity).

If FuncSpec is tuple {FS}, FS is the first argument to erlang:trace_pattern/3. For example, if FuncSpec is {on_load}, call counters will be set to zero and running for all functions in modules to be loaded.

start(Mod, Func)

-spec start(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().

Equivalent to start(Mod, Func, '_').

start(Mod, Func, Arity)

-spec start(Mod, Func, Arity) -> non_neg_integer()
               when Mod :: module(), Func :: atom(), Arity :: arity().

Start call count tracing for matching functions in matching modules.

Set call count breakpoints on the matching functions that has no call count breakpoints. Call counters are set to zero and running for all matching functions.

Return the number of matching functions that has call count breakpoints.

stop()

-spec stop() -> non_neg_integer().

Stop call count tracing for all functions in all modules, and also for all functions in modules to be loaded.

This is equivalent to stop('_', '_', '_') + stop({on_load}).

stop(FuncSpec)

-spec stop(FuncSpec) -> non_neg_integer() when FuncSpec :: (Mod :: module()) | mfa() | {FS :: term()}.

If FuncSpec is an atom, it is assumed to be a module name, and this call is equivalent to stop(FuncSpec, '_', '_').

If FuncSpec is an MFA tuple, {Module, Name, Arity}, this call is equivalent to stop(Module, Name, Arity).

If FuncSpec is tuple {FS}, FS is the first argument to erlang:trace_pattern/3. For example, if FuncSpec is {on_load}, call counters be disabled for all functions in modules to be loaded.

stop(Mod, Func)

-spec stop(Mod, Func) -> non_neg_integer() when Mod :: module(), Func :: atom().

Equivalent to stop(Mod, Func, '_').

stop(Mod, Func, Arity)

-spec stop(Mod, Func, Arity) -> non_neg_integer() when Mod :: module(), Func :: atom(), Arity :: arity().

Stop call count tracing for matching functions in matching modules.

Remove call count breakpoints from the matching functions that has call count breakpoints.

Return the number of matching functions that can have call count breakpoints, which is the same as start/* with the same arguments would have returned.

crashdump

A Tool for Handling Erlang Crash Dumps

This module contains functions for decrypting encrypted Erlang crash dumps, which can be enabled with the --enable-encrypted-crash-dumps build flag.

Summary

Functions

decrypt(EncryptedFile, PrivateKey)

Decrypts the Erlang crash dump at EncryptedFile using PrivateKey.

decrypt(EncryptedFile, PrivateKey, DecryptedFile)

Decrypts the Erlang crash dump at EncryptedFile using PrivateKey, writing the result to DecryptedFile.

pem_decrypt(EncryptedFile, KeyFile)

This is a convenience wrapper around crashdump:decrypt/2 that handles key extraction from a given PEM file.

pem_decrypt(EncryptedFile, KeyFile, DecryptedFile)

This is a convenience wrapper around crashdump:decrypt/3 that handles key extraction from a given PEM file.

Functions

decrypt(EncryptedFile, PrivateKey)

(since OTP @OTP-20085@)

-spec decrypt(EncryptedFile, PrivateKey) -> {ok, erlang:iovec()} | {error, Reason}
                 when
                     EncryptedFile :: file:name(),
                     PrivateKey :: public_key:private_key(),
                     Reason :: dynamic().

Decrypts the Erlang crash dump at EncryptedFile using PrivateKey.

decrypt(EncryptedFile, PrivateKey, DecryptedFile)

(since OTP @OTP-20085@)

-spec decrypt(EncryptedFile, PrivateKey, DecryptedFile) -> ok | {error, Reason}
                 when
                     EncryptedFile :: file:name(),
                     PrivateKey :: public_key:private_key(),
                     DecryptedFile :: file:name(),
                     Reason :: dynamic().

Decrypts the Erlang crash dump at EncryptedFile using PrivateKey, writing the result to DecryptedFile.

pem_decrypt(EncryptedFile, KeyFile)

(since OTP @OTP-20085@)

-spec pem_decrypt(EncryptedFile, KeyFile) -> {ok, erlang:iovec()} | {error, Reason}
                     when EncryptedFile :: file:name(), KeyFile :: file:name(), Reason :: dynamic().

This is a convenience wrapper around crashdump:decrypt/2 that handles key extraction from a given PEM file.

pem_decrypt(EncryptedFile, KeyFile, DecryptedFile)

(since OTP @OTP-20085@)

-spec pem_decrypt(EncryptedFile, KeyFile, DecryptedFile) -> ok | {error, Reason}
                     when
                         EncryptedFile :: file:name(),
                         KeyFile :: file:name(),
                         DecryptedFile :: file:name(),
                         Reason :: dynamic().

This is a convenience wrapper around crashdump:decrypt/3 that handles key extraction from a given PEM file.

eprof

A Time Profiling Tool for Erlang

The module eprof provides a set of functions for time profiling of Erlang programs to find out how the execution time is used. The profiling is done using the Erlang trace BIFs. Tracing of local function calls for a specified set of processes is enabled when profiling is begun, and disabled when profiling is stopped.

When using Eprof, expect a slowdown in program execution.

Summary

Types

analyze_type()

trace_pattern_mfa()

Functions

analyze()

Equivalent to analyze(procs, []).

analyze(TypeOpts)

If TypeOpts is an atom, it is assumed to be a module name, and this call is equivalent to analyze(TypeOpts, []).

analyze(Type, Options)

Call this function when profiling has been stopped to display the results.

log(File)

Call this function to ensure that the results displayed by analyze/0,1,2 are printed to the file File as well as to the screen.

profile(FunRootset)

If FunRootset is a fun, this call is equivalent to profile([], FunRootset).

profile(Arg1, Arg2)

If Arg1 is a fun and Arg2 is list, this call is equivalent to profile([], Arg1, {'_','_','_'}, Arg2).

profile(Rootset, Fun, Pattern)

Equivalent to profile(Rootset, Fun, Pattern, [{set_on_spawn, true}]).

profile(Rootset, Arg1, Arg2, Arg3)

This function spawns a process that applies a fun or an an function, and then starts profiling for the spawned proceses as well as the processes in Rootset (and any new processes spawned from them).

profile(Rootset, Module, Function, Args, Pattern)

Equivalent to profile(Rootset, Module, Function, Args, Pattern, [{set_on_spawn, true}]).

profile(Rootset, Module, Function, Args, Pattern, Options)

This function spawns a process P that apply(Module, Function, Args), and then starts profiling for P and the processes in Rootset (and any new processes spawned from them).

start()

Starts the Eprof server which holds the internal state of the collected data.

start_profiling(Rootset)

Equivalent to start_profiling(Rootset, {'_', '_', '_'}).

start_profiling(Rootset, Pattern)

Equivalent to start_profiling(Rootset, Pattern, [{set_on_spawn, true}]).

start_profiling(Rootset, Pattern, Options)

Starts profiling for the processes in Rootset (and any new processes spawned from them).

stop()

Stops the Eprof server.

stop_profiling()

Stops profiling started with start_profiling/1 or profile/1.

Types

analyze_type()

(not exported)

-type analyze_type() :: procs | total.

trace_pattern_mfa()

(not exported)

-type trace_pattern_mfa() :: {atom(), atom(), arity() | '_'}.

Functions

analyze()

(since OTP R14B)

-spec analyze() -> ok | nothing_to_analyze.

Equivalent to analyze(procs, []).

analyze(TypeOpts)

(since OTP R14B)

-spec analyze(TypeOpts) -> ok | nothing_to_analyze when TypeOpts :: analyze_type().

If TypeOpts is an atom, it is assumed to be a module name, and this call is equivalent to analyze(TypeOpts, []).

Otherwise, if TypeOpts is a list, it assumed to be a list of options, and this call is equivalent to analyze(procs, TypeOpts).

analyze(Type, Options)

(since OTP R14B)

-spec analyze(Type, Options) -> ok | nothing_to_analyze
                 when
                     Type :: analyze_type(),
                     Options :: [Option],
                     Option :: {filter, Filter} | {sort, Sort},
                     Filter :: [{calls, non_neg_integer()} | {time, float()}],
                     Sort :: time | calls | mfa.

Call this function when profiling has been stopped to display the results.

If Type is procs, the time spent in each function is shown separately for each profiled process.

If Type is total, the time spent in each function is shown combined for each profiled process.

Time is shown as percentage of total time and as absolute time in micro seconds.

log(File)

-spec log(File) -> ok when File :: atom() | file:filename().

Call this function to ensure that the results displayed by analyze/0,1,2 are printed to the file File as well as to the screen.

profile(FunRootset)

-spec profile(Fun) -> {ok, Value} | {error, Reason}
                 when Fun :: fun(() -> term()), Value :: term(), Reason :: term();
             (Rootset) -> profiling | {error, Reason} when Rootset :: [atom() | pid()], Reason :: term().

If FunRootset is a fun, this call is equivalent to profile([], FunRootset).

If FunRootset is a list, it is assumed to be a Rootset, and this call is equivalent to start_profiling(Rootset).

profile(Arg1, Arg2)

-spec profile(Fun, Options) -> {ok, Value} | {error, Reason}
                 when
                     Fun :: fun(() -> term()),
                     Options :: [set_on_spawn | {set_on_spawn, boolean()}],
                     Value :: term(),
                     Reason :: term();
             (Rootset, Fun) -> {ok, Value} | {error, Reason}
                 when
                     Rootset :: [atom() | pid()],
                     Fun :: fun(() -> term()),
                     Value :: term(),
                     Reason :: term().

If Arg1 is a fun and Arg2 is list, this call is equivalent to profile([], Arg1, {'_','_','_'}, Arg2).

If Arg1 is a list and Arg2 is a fun, this call is equivalent to profile(Arg1, Arg2, {'_','_','_'}, Arg1).

profile(Rootset, Fun, Pattern)

(since OTP R14B)

-spec profile(Rootset, Fun, Pattern) -> {ok, Value} | {error, Reason}
                 when
                     Rootset :: [atom() | pid()],
                     Fun :: fun(() -> term()),
                     Pattern :: trace_pattern_mfa(),
                     Value :: term(),
                     Reason :: term().

Equivalent to profile(Rootset, Fun, Pattern, [{set_on_spawn, true}]).

profile(Rootset, Arg1, Arg2, Arg3)

-spec profile(Rootset, Module, Function, Args) -> {ok, Value} | {error, Reason}
                 when
                     Rootset :: [atom() | pid()],
                     Module :: module(),
                     Function :: atom(),
                     Args :: [term()],
                     Value :: term(),
                     Reason :: term();
             (Rootset, Fun, Pattern, Options) -> {ok, Value} | {error, Reason}
                 when
                     Rootset :: [atom() | pid()],
                     Fun :: fun(() -> term()),
                     Pattern :: trace_pattern_mfa(),
                     Options :: [set_on_spawn | {set_on_spawn, boolean()}],
                     Value :: term(),
                     Reason :: term().

This function spawns a process that applies a fun or an an function, and then starts profiling for the spawned proceses as well as the processes in Rootset (and any new processes spawned from them).

If Arg1 is a fun, Arg2 is expected to be a trace pattern, and Arg3 a list of options. In that case, this call is equivalent to:

profile(Rootset, erlang, apply, [Arg1, []], Arg2, Arg3)

If Arg1 is an atom, Arg1 is assumed to be a module name, Arg2 the name of the function in that module, and Arg3 a list of arguments to be used when calling that function. In that case, this call is equivalent to:

profile(Rootset, Arg1, Arg2, Arg3, {'_','_','_'}, [{set_on_spawn, true}])

profile(Rootset, Module, Function, Args, Pattern)

(since OTP R14B)

-spec profile(Rootset, Module, Function, Args, Pattern) -> {ok, Value} | {error, Reason}
                 when
                     Rootset :: [atom() | pid()],
                     Module :: module(),
                     Function :: atom(),
                     Args :: [term()],
                     Pattern :: trace_pattern_mfa(),
                     Value :: term(),
                     Reason :: term().

Equivalent to profile(Rootset, Module, Function, Args, Pattern, [{set_on_spawn, true}]).

profile(Rootset, Module, Function, Args, Pattern, Options)

(since OTP R16B01)

-spec profile(Rootset, Module, Function, Args, Pattern, Options) -> {ok, Value} | {error, Reason}
                 when
                     Rootset :: [atom() | pid()],
                     Module :: module(),
                     Function :: atom(),
                     Args :: [term()],
                     Pattern :: trace_pattern_mfa(),
                     Options :: [set_on_spawn | {set_on_spawn, boolean()}],
                     Value :: term(),
                     Reason :: term().

This function spawns a process P that apply(Module, Function, Args), and then starts profiling for P and the processes in Rootset (and any new processes spawned from them).

Rootset is a list of pids and registered names.

Information about activity in any profiled process is stored in the Eprof database.

If tracing could be enabled for P and all processes in Rootset, the function returns {ok,Value} when Fun()/apply returns with the value Value, or {error,Reason} if Fun()/apply fails with exit reason Reason. Otherwise it returns {error, Reason} immediately.

The set_on_spawn option will active call time tracing for all processes spawned by processes in the rootset. This is the default behaviour.

The programmer must ensure that the function given as argument is truly synchronous and that no work continues after the function has returned a value.

start()

-spec start() -> {ok, Pid} | {error, Reason} when Pid :: pid(), Reason :: {already_started, Pid}.

Starts the Eprof server which holds the internal state of the collected data.

start_profiling(Rootset)

-spec start_profiling(Rootset) -> profiling | {error, Reason}
                         when Rootset :: [atom() | pid()], Reason :: term().

Equivalent to start_profiling(Rootset, {'_', '_', '_'}).

start_profiling(Rootset, Pattern)

(since OTP R14B)

-spec start_profiling(Rootset, Pattern) -> profiling | {error, Reason}
                         when
                             Rootset :: [atom() | pid()],
                             Pattern :: trace_pattern_mfa(),
                             Reason :: term().

Equivalent to start_profiling(Rootset, Pattern, [{set_on_spawn, true}]).

start_profiling(Rootset, Pattern, Options)

(since OTP R16B01)

-spec start_profiling(Rootset, Pattern, Options) -> profiling | {error, Reason}
                         when
                             Rootset :: [atom() | pid()],
                             Pattern :: trace_pattern_mfa(),
                             Options :: [set_on_spawn | {set_on_spawn, boolean()}],
                             Reason :: term().

Starts profiling for the processes in Rootset (and any new processes spawned from them).

Information about activity in any profiled process is stored in the Eprof database.

Rootset is a list of pids and registered names.

The function returns profiling if tracing could be enabled for all processes in Rootset, or error otherwise.

A pattern can be selected to narrow the profiling. For instance a specific module can be selected, and only the code executed in that module will be profiled.

The set_on_spawn option will active call time tracing for all processes spawned by processes in the rootset. This is the default behaviour.

stop()

-spec stop() -> stopped.

Stops the Eprof server.

stop_profiling()

-spec stop_profiling() -> profiling_stopped | profiling_already_stopped.

Stops profiling started with start_profiling/1 or profile/1.

fprof

A Time Profiling Tool using trace to file for minimal runtime performance impact.

This module is used to profile a program to find out how the execution time is used. Tracing to file is used to minimize the runtime performance degradation.

The fprof module uses tracing to collect profiling data, hence there is no need for special compilation of any module to be profiled. When it starts tracing, fprof will erase all previous tracing in the node and set the necessary trace flags on the profiling target processes as well as local call trace on all functions in all loaded modules and all modules to be loaded. fprof disable all tracing in the node when it stops tracing.

fprof presents both own time that is, how much time a function has used for its own execution, and accumulated time that is, including called functions. All presented times are collected using trace timestamps. fprof tries to collect CPU time timestamps, if the host machine OS supports it. Therefore, the times can be wallclock times and OS scheduling will randomly strike all called functions in a presumably fair way.

However, if the profiling time is short, and the host machine OS does not support high resolution CPU time measurements, a few OS schedulings can show up as ridiculously long execution times for functions doing practically nothing. As an example, it has been observed that a function that more or less just composing a tuple, was running 100 times slower than normal. When tracing was repeated, the execution time was normal.

Profiling is essentially done in 3 steps:

Tracing: to a file. The trace data contains entries for function calls, returns to function, process scheduling, other process related events (for example spawn), and garbage collection. All trace entries are timestamped.

Profiling: the trace file is read, the execution call stack is simulated, and raw profile data is calculated from the simulated call stack and the trace timestamps. The profile data is stored in the fprof server state. During this step the trace data may be dumped in text format to file or console.

Analysing: the raw profile data is sorted, filtered and dumped in text format either to file or console. The text format intended to be both readable for a human reader, as well as parsable with the standard erlang parsing tools.

Since fprof sends trace data to afile, the runtime performance degradation is minimized, but still far from negligible, especially for programs that themselves use the filesystem heavily. Where the trace file is placed is also important, for example, on Unix systems /tmp is usually a good choice since it is essentially a RAM disk, while any network-mounted disk is a bad idea.

fprof can also skip the file step and trace to a tracer process that does the profiling in runtime.

Analysis format

This section describes the output format of the analyse/1 function.

The format is parsable with the standard Erlang parsing tools erl_scan and erl_parse, file:consult/1, or io:read/2. The parse format is not described here — it should be easy enough for the interested reader to try it out. Note that some flags to analyse/1 will affect the format.

The following example was run on Erlang/OTP R8 on Solaris 8; all OTP internals in this example are version dependent.

As an example, we will use the following function, which is a slightly modified benchmark function from module file:

-module(foo).
-export([create_file_slow/2]).

create_file_slow(Name, N) when is_integer(N), N >= 0 ->
    {ok, FD} =
        file:open(Name, [raw, write, delayed_write, binary]),
    if N > 256 ->
            ok = file:write(FD,
                            lists:map(fun (X) -> <<X:32/unsigned>> end,
                            lists:seq(0, 255))),
            ok = create_file_slow(FD, 256, N);
       true ->
            ok = create_file_slow(FD, 0, N)
    end,
    ok = file:close(FD).

create_file_slow(FD, M, M) ->
    ok;
create_file_slow(FD, M, N) ->
    ok = file:write(FD, <<M:32/unsigned>>),
    create_file_slow(FD, M+1, N).

Let us have a look at the printout after running:

1> fprof:apply(foo, create_file_slow, [junk, 1024]).
2> fprof:profile().
3> fprof:analyse().

The printout starts with:

%% Analysis results:
{  analysis_options,
 [{callers, true},
  {sort, acc},
  {totals, false},
  {details, true}]}.

%                                       CNT       ACC       OWN
[{ totals,                             9627, 1691.119, 1659.074}].  %%%

The CNT column shows the total number of function calls that was found in the trace. In the ACC column is the total time of the trace from first timestamp to last. And in the OWN column is the sum of the execution time in functions found in the trace, not including called functions. In this case it is very close to the ACC time since the emulator had practically nothing to do except executing our test program.

All time values in the printout are in milliseconds.

The printout continues:

%                                       CNT       ACC       OWN
[{ "<0.28.0>",                         9627,undefined, 1659.074}].   %%

This is the printout header of one process. The printout contains only this one process since we called fprof:apply/3 that traces only the current process. Therefore the CNT and OWN columns perfectly matches the totals above. The ACC column is undefined since summing the ACC times of all calls in the process makes no sense — one would get something like the ACC value from totals above multiplied by the average depth of the call stack.

All paragraphs up to the next process header only concerns function calls within this process.

Now we come to something more interesting:

{[{undefined,                             0, 1691.076,    0.030}],
 { {fprof,apply_start_stop,4},            0, 1691.076,    0.030},     %
 [{{foo,create_file_slow,2},              1, 1691.046,    0.103},
  {suspend,                               1,    0.000,    0.000}]}.

{[{{fprof,apply_start_stop,4},            1, 1691.046,    0.103}],
 { {foo,create_file_slow,2},              1, 1691.046,    0.103},     %
 [{{file,close,1},                        1, 1398.873,    0.019},
  {{foo,create_file_slow,3},              1,  249.678,    0.029},
  {{file,open,2},                         1,   20.778,    0.055},
  {{lists,map,2},                         1,   16.590,    0.043},
  {{lists,seq,2},                         1,    4.708,    0.017},
  {{file,write,2},                        1,    0.316,    0.021}]}.

The printout consists of one paragraph per called function. The function marked with % is the one the paragraph concerns — foo:create_file_slow/2. Above the marked function are the calling functions — those that has called the marked, and below are those called by the marked function.

The paragraphs are per default sorted in descending order of the ACC column for the marked function. The calling list and called list within one paragraph are also per default sorted in descending order of their ACC column.

The columns are:

CNT - the number of times the function has been called

ACC - the time spent in the function including called functions

OWN - the time spent in the function not including called functions

The rows for the calling functions contain statistics for the marked function with the constraint that only the occasions when a call was made from the row's function to the marked function are accounted for.

The row for the marked function simply contains the sum of all calling rows.

The rows for the called functions contains statistics for the row's function with the constraint that only the occasions when a call was made from the marked to the row's function are accounted for.

So, we see that foo:create_file_slow/2 used very little time for its own execution. It spent most of its time in file:close/1. The function foo:create_file_slow/3 that writes 3/4 of the file contents is the second biggest time thief.

We also see that the call to file:write/2 that writes 1/4 of the file contents takes very little time in itself. What takes time is to build the data (lists:seq/2 and lists:map/2).

The function undefined that has called fprof:apply_start_stop/4 is an unknown function because that call was not recorded in the trace. It was only recorded that the execution returned from fprof:apply_start_stop/4 to some other function above in the call stack, or that the process exited from there.

Let us continue down the printout to find:

{[{{foo,create_file_slow,2},              1,  249.678,    0.029},
  {{foo,create_file_slow,3},            768,    0.000,   23.294}],
 { {foo,create_file_slow,3},            769,  249.678,   23.323},     %
 [{{file,write,2},                      768,  220.314,   14.539},
  {suspend,                              57,    6.041,    0.000},
  {{foo,create_file_slow,3},            768,    0.000,   23.294}]}.

If you compare with the code you will see there also that foo:create_file_slow/3 was called only from foo:create_file_slow/2 and itself, and called only file:write/2, note the number of calls to file:write/2. But here we see that suspend was called a few times. This is a pseudo function that indicates that the process was suspended while executing in foo:create_file_slow/3, and since there is no receive or erlang:yield/0 in the code, it must be Erlang scheduling suspensions, or the trace file driver compensating for large file write operations (these are regarded as a schedule out followed by a schedule in to the same process).

Let us find the suspend entry:

{[{{file,write,2},                       53,    6.281,    0.000},
  {{foo,create_file_slow,3},             57,    6.041,    0.000},
  {{prim_file,drv_command,4},            50,    4.582,    0.000},
  {{prim_file,drv_get_response,1},       34,    2.986,    0.000},
  {{lists,map,2},                        10,    2.104,    0.000},
  {{prim_file,write,2},                  17,    1.852,    0.000},
  {{erlang,port_command,2},              15,    1.713,    0.000},
  {{prim_file,drv_command,2},            22,    1.482,    0.000},
  {{prim_file,translate_response,2},     11,    1.441,    0.000},
  {{prim_file,'-drv_command/2-fun-0-',1},  15,    1.340,    0.000},
  {{lists,seq,4},                         3,    0.880,    0.000},
  {{foo,'-create_file_slow/2-fun-0-',1},   5,    0.523,    0.000},
  {{erlang,bump_reductions,1},            4,    0.503,    0.000},
  {{prim_file,open_int_setopts,3},        1,    0.165,    0.000},
  {{prim_file,i32,4},                     1,    0.109,    0.000},
  {{fprof,apply_start_stop,4},            1,    0.000,    0.000}],
 { suspend,                             299,   32.002,    0.000},     %
 [ ]}.

We find no particularly long suspend times, so no function seems to have waited in a receive statement. Actually, prim_file:drv_command/4 contains a receive statement, but in this test program, the message lies in the process receive buffer when the receive statement is entered. We also see that the total suspend time for the test run is small.

The suspend pseudo function has an OWN time of zero. This is to prevent the process total OWN time from including time in suspension. Whether suspend time is really ACC or OWN time is more of a philosophical question.

Now we look at another interesting pseudo function, garbage_collect:

{[{{prim_file,drv_command,4},            25,    0.873,    0.873},
  {{prim_file,write,2},                  16,    0.692,    0.692},
  {{lists,map,2},                         2,    0.195,    0.195}],
 { garbage_collect,                      43,    1.760,    1.760},     %
 [ ]}.

Here we see that no function stands out, which is very normal.

The garbage_collect pseudo function has not an OWN time of zero like suspend, instead it is equal to the ACC time.

Garbage collection often occurs while a process is suspended, but fprof hides this fact by pretending that the suspended function was first unsuspended and then garbage collected. Otherwise the printout would show garbage_collect being called from suspend, but not which function that might have caused the garbage collection.

Let us now get back to the test code:

{[{{foo,create_file_slow,3},            768,  220.314,   14.539},
  {{foo,create_file_slow,2},              1,    0.316,    0.021}],
 { {file,write,2},                      769,  220.630,   14.560},     %
 [{{prim_file,write,2},                 769,  199.789,   22.573},
  {suspend,                              53,    6.281,    0.000}]}.

Not unexpectedly, we see that file:write/2 was called from foo:create_file_slow/3 and foo:create_file_slow/2. The number of calls in each case as well as the used time are also confirms the previous results.

We see that file:write/2 only calls prim_file:write/2, but let us refrain from digging into the internals of the kernel application.

If we nevertheless do dig down we find the call to the linked-in driver that does the file operations towards the host operating system:

{[{{prim_file,drv_command,4},           772, 1458.356, 1456.643}],
 { {erlang,port_command,2},             772, 1458.356, 1456.643},     %
 [{suspend,                              15,    1.713,    0.000}]}.

This is 86 % of the total run time, and as we saw before it is the close operation the absolutely biggest contributor. We find a comparison ratio a little bit up in the call stack:

{[{{prim_file,close,1},                   1, 1398.748,    0.024},
  {{prim_file,write,2},                 769,  174.672,   12.810},
  {{prim_file,open_int,4},                1,   19.755,    0.017},
  {{prim_file,open_int_setopts,3},        1,    0.147,    0.016}],
 { {prim_file,drv_command,2},           772, 1593.322,   12.867},     %
 [{{prim_file,drv_command,4},           772, 1578.973,   27.265},
  {suspend,                              22,    1.482,    0.000}]}.

The time for file operations in the linked in driver distributes itself as 1 % for open, 11 % for write, and 87 % for close. All data is probably buffered in the operating system until the close.

The observant reader may notice that the ACC times for prim_file:drv_command/2 and prim_file:drv_command/4 is not equal between the paragraphs above, even though it is easy to believe that prim_file:drv_command/2 is just a passthrough function.

The missing time can be found in the paragraph for prim_file:drv_command/4 where it is evident that not only prim_file:drv_command/2 is called but also a fun:

{[{{prim_file,drv_command,2},           772, 1578.973,   27.265}],
 { {prim_file,drv_command,4},           772, 1578.973,   27.265},     %
 [{{erlang,port_command,2},             772, 1458.356, 1456.643},
  {{prim_file,'-drv_command/2-fun-0-',1}, 772,   87.897,   12.736},
  {suspend,                              50,    4.582,    0.000},
  {garbage_collect,                      25,    0.873,    0.873}]}.

And some more missing time can be explained by the fact that prim_file:open_int/4 both calls prim_file:drv_command/2 directly as well as through prim_file:open_int_setopts/3, which complicates the picture.

{[{{prim_file,open,2},                    1,   20.309,    0.029},
  {{prim_file,open_int,4},                1,    0.000,    0.057}],
 { {prim_file,open_int,4},                2,   20.309,    0.086},     %
 [{{prim_file,drv_command,2},             1,   19.755,    0.017},
  {{prim_file,open_int_setopts,3},        1,    0.360,    0.032},
  {{prim_file,drv_open,2},                1,    0.071,    0.030},
  {{erlang,list_to_binary,1},             1,    0.020,    0.020},
  {{prim_file,i32,1},                     1,    0.017,    0.017},
  {{prim_file,open_int,4},                1,    0.000,    0.057}]}.
.
.
.
{[{{prim_file,open_int,4},                1,    0.360,    0.032},
  {{prim_file,open_int_setopts,3},        1,    0.000,    0.016}],
 { {prim_file,open_int_setopts,3},        2,    0.360,    0.048},     %
 [{suspend,                               1,    0.165,    0.000},
  {{prim_file,drv_command,2},             1,    0.147,    0.016},
  {{prim_file,open_int_setopts,3},        1,    0.000,    0.016}]}.

Notes on accuracy of measurements

The actual supervision of execution times is in itself a CPU-intensive activity. A message is written on the trace file for every function call that is made by the profiled code.

The ACC time calculation is sometimes difficult to make correct, since it is difficult to define. This happens especially when a function occurs in several instances in the call stack, for example by calling itself perhaps through other functions and perhaps even non-tail recursively.

To produce sensible results, fprof tries not to charge any function more than once for ACC time. The instance highest up (with longest duration) in the call stack is chosen.

Sometimes a function can unexpectedly waste a lot (some 10 ms or more depending on host machine OS) of OWN (and ACC) time, even functions that do practically nothing at all. The problem may be that the OS has chosen to schedule out the Erlang runtime system process for a while, and if the OS does not support high resolution CPU time measurements fprof will use wallclock time for its calculations, and it will appear as if functions are randomly burning virtual machine time.

See Also

fprof - The File Trace Profiler, dbg, eprof

Summary

Types

analyse_option()

apply_option()

pid_spec()

profile_option()

trace_option()

Functions

analyse()

Equivalent to analyse([]).

analyse(Arg)

Analyses raw profile data in the fprof server.

analyse(OptionName, OptionValue)

Equivalent to analyse([{OptionName, OptionValue}]).

apply(Func, Args)

Equivalent to apply(Func, Args, []).

apply(Arg1, Arg2, Arg3)

Calls the given function surrounded by trace([start, ...]) and trace(stop).

apply(Module, Function, Args, OptionList)

Equivalent to apply({Module, Function}, Args, OptionList).

profile()

Equivalent to profile([]).

profile(Arg)

Compiles a trace into raw profile data held by the fprof server.

profile(OptionName, OptionValue)

Equivalent to profile([{OptionName, OptionValue}]).

start()

Starts the fprof server.

stop()

Equivalent to stop(normal).

stop(Reason)

Stops the fprof server.

trace(Arg)

Starts or stops tracing.

trace(What, Value)

Starts or stop tracing.

Types

analyse_option()

(not exported)

-type analyse_option() ::
          append | callers |
          {callers, boolean()} |
          {cols, Cols :: non_neg_integer()} |
          dest |
          {dest, Dest :: pid() | (Destfile :: file:filename())} |
          details |
          {details, boolean()} |
          no_callers | no_details |
          {sort, SortSpec :: acc | own} |
          totals |
          {totals, boolean()}.

apply_option()

(not exported)

-type apply_option() ::
          continue | {procs, PidList :: [pid()]} | start | (TraceStartOption :: trace_option()).

pid_spec()

(not exported)

-type pid_spec() :: pid() | atom().

profile_option()

(not exported)

-type profile_option() ::
          append | dump |
          {dump, pid() | (Dump :: (Dumpfile :: file:filename() | []))} |
          file |
          {file, Filename :: file:filename()} |
          start | stop.

trace_option()

(not exported)

-type trace_option() ::
          cpu_time |
          {cpu_time, boolean()} |
          file |
          {file, Filename :: file:filename()} |
          {procs, PidSpec :: pid_spec()} |
          {procs, [PidSpec :: pid_spec()]} |
          start | stop |
          {tracer, Tracer :: pid() | port()} |
          verbose |
          {verbose, boolean()}.

Functions

analyse()

-spec analyse() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when ServerPid :: pid(), Reason :: term().

Equivalent to analyse([]).

analyse(Arg)

-spec analyse(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when OptionName :: atom(), ServerPid :: pid(), Reason :: term();
             ({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when OptionName :: atom(), OptionValue :: term(), ServerPid :: pid(), Reason :: term();
             (OptionList) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when
                     OptionList :: [Option],
                     Option :: analyse_option(),
                     ServerPid :: pid(),
                     Reason :: term().

Analyses raw profile data in the fprof server.

If Arg is an atom, this call is equivalent to analyse([Arg]).

If Arg is a a tuple {Option, _}, this call is equivalent to analyse([Option]).

Otherwise Arg must be a list of valid options.

If called when no raw profile data is available, {error, no_profile} is returned.

Destfile is used to call file:open/2.

Option description:

dest | {dest, Dest} - Specifies the destination for the analysis. If this option is not given or it is dest, the destination will be the caller's group leader, otherwise the destination Dest is either the pid/0 of an I/O device or a filename. If the filename is [], "fprof.analysis" is used instead.

append - Causes the analysis to be appended to the destination file. This option is only allowed with the {dest, Destfile} option.

{cols, Cols} - Specifies the number of columns in the analysis text. If this option is not given the number of columns is set to 80.

callers | {callers, true} - Prints callers and called information in the analysis. This is the default.

{callers, false} | no_callers - Suppresses the printing of callers and called information in the analysis.

{sort, SortSpec} - Specifies if the analysis should be sorted according to the ACC column, which is the default, or the OWN column. See Analysis Format below.

totals | {totals, true} - Includes a section containing call statistics for all calls regardless of process, in the analysis.

{totals, false} - Suppresses the totals section in the analysis, which is the default.

details | {details, true} - Prints call statistics for each process in the analysis. This is the default.

{details, false} | no_details - Suppresses the call statistics for each process from the analysis.

analyse(OptionName, OptionValue)

-spec analyse(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when OptionName :: atom(), OptionValue :: term(), ServerPid :: pid(), Reason :: term().

Equivalent to analyse([{OptionName, OptionValue}]).

apply(Func, Args)

-spec apply(Func, Args) -> term()
               when Func :: fun() | {Module :: module(), Function :: atom()}, Args :: [term()].

Equivalent to apply(Func, Args, []).

apply(Arg1, Arg2, Arg3)

-spec apply(Module, Function, Args) -> term()
               when Module :: module(), Function :: atom(), Args :: [term()];
           (Func, Args, OptionList) -> term()
               when
                   Func :: fun() | {Module :: module(), Function :: atom()},
                   Args :: [term()],
                   OptionList :: [Option],
                   Option :: apply_option().

Calls the given function surrounded by trace([start, ...]) and trace(stop).

If the function arguments (Arg1, Arg2, and Arg3) are Module (an atom), Function (an atom), and Args (a list), the function will be called using erlang:apply(Module, Function, Args).

If the function arguments are Func (a fun), Args (a list), and OptionList (a list of options), the fun will be called using erlang:apply(Func, Args).

Some effort is made to keep the trace clean from unnecessary trace messages; tracing is started and stopped from a spawned process while erlang:apply/2 is called in the current process only surrounded by receive and send statements towards the trace starting process. The trace starting process exits when it is not needed any more.

The TraceStartOption is any option allowed for trace/1. The options [start, {procs, [self() | PidList]} | OptList] are given to trace/1, where OptList is OptionList with the continue, start and {procs, _} options removed.

The continue option inhibits the call to trace(stop) and leaves it up to the caller to stop tracing at a suitable time.

apply(Module, Function, Args, OptionList)

-spec apply(Module, Function, Args, OptionList) -> term()
               when
                   Module :: module(),
                   Function :: atom(),
                   Args :: [term()],
                   OptionList :: [Option],
                   Option :: apply_option().

Equivalent to apply({Module, Function}, Args, OptionList).

profile()

-spec profile() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when ServerPid :: pid(), Reason :: term().

Equivalent to profile([]).

profile(Arg)

-spec profile(OptionName) -> ok | {ok, Tracer} | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when OptionName :: atom(), Tracer :: pid(), ServerPid :: pid(), Reason :: term();
             ({OptionName, OptionValue}) ->
                 ok | {ok, Tracer} | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when
                     OptionName :: atom(),
                     OptionValue :: term(),
                     Tracer :: pid(),
                     ServerPid :: pid(),
                     Reason :: term();
             (OptionList) -> ok | {ok, Tracer} | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when
                     OptionList :: [Option],
                     Option :: profile_option(),
                     Tracer :: pid(),
                     ServerPid :: pid(),
                     Reason :: term().

Compiles a trace into raw profile data held by the fprof server.

If Arg is an atom, this call is equivalent to profile([Arg]).

If Arg is a tuple {OptionName, OptionValue}, this call is equivalent to profile([Arg]).

Otherwise, Arg must be a list of options.

Dumpfile is used to call file:open/2, and Filename is used to call dbg:trace_port(file, Filename).

The following options are supported:

file | {file, Filename} - Reads the file Filename and creates raw profile data that is stored in RAM by the fprof server. If the option file is given, or none of these options are given, the file fprof.trace is read. The call will return when the whole trace has been read with the return value ok if successful. This option is not allowed with the start or stop options.

dump | {dump, Dump} - Specifies the destination for the trace text dump. If this option is not given, no dump is generated, if it is dump the destination will be the caller's group leader, otherwise the destination Dump is either the pid of an I/O device or a filename. If the filename is [], "fprof.dump" is used instead. This option cannot be combined with the stop option.

append - Causes the trace text dump to be appended to the destination file. This option is only allowed with the {dump, Dumpfile} option.

start - Starts a tracer process that profiles trace data in runtime. The call will return immediately with the return value {ok, Tracer} if successful. This option is not allowed with the stop, file, or {file, Filename} options.

stop - Stops the tracer process that profiles trace data in runtime. The return value will be value ok if successful. This option cannot be combined with the start, file, or {file, Filename} options.

profile(OptionName, OptionValue)

-spec profile(OptionName, OptionValue) ->
                 ok | {ok, Tracer} | {error, Reason} | {'EXIT', ServerPid, Reason}
                 when
                     OptionName :: atom(),
                     OptionValue :: term(),
                     Tracer :: pid(),
                     ServerPid :: pid(),
                     Reason :: term().

Equivalent to profile([{OptionName, OptionValue}]).

start()

-spec start() -> {ok, Pid} | {error, {already_started, Pid}} when Pid :: pid().

Starts the fprof server.

Note that there is seldom any need to call this function directly, since the server will be automatically started by any function that will need it.

stop()

-spec stop() -> ok.

Equivalent to stop(normal).

stop(Reason)

-spec stop(Reason) -> ok when Reason :: term().

Stops the fprof server.

The supplied Reason becomes the exit reason for the server process. By default, any Reason other than kill sends a request to the server and waits for it to clean up, reply, and exit. If Reason is kill, the server is bluntly killed.

If the fprof server is not running, this function returns immediately.

Note

When the fprof server is stopped the collected raw profile data is lost.

trace(Arg)

-spec trace(verbose) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
               when ServerPid :: pid(), Reason :: term();
           (OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
               when OptionName :: atom(), ServerPid :: pid(), Reason :: term();
           ({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
               when OptionName :: atom(), OptionValue :: term(), ServerPid :: pid(), Reason :: term();
           (OptionList) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
               when
                   OptionList :: [Option],
                   Option :: trace_option(),
                   ServerPid :: pid(),
                   Reason :: term().

Starts or stops tracing.

If Arg is atom verbose, this call is equivalent to trace([start, verbose]).

If Arg is an atom, this call is equivalent to trace([Arg]).

If Arg is a tuple {OptionName, OptionValue}, this call is equivalent to trace([Arg]).

Otherwise, Arg has to be a list of trace options.

PidSpec and Tracer are used in calls to erlang:trace(PidSpec, true, [{tracer, Tracer} | Flags]), and Filename is used to call dbg:trace_port(file, Filename).

Option description:

stop - Stops a running fprof trace and clears all tracing from the node. Either option stop or start must be specified, but not both.

start - Clears all tracing from the node and starts a new fprof trace. Either option start or stop must be specified, but not both.

verbose | {verbose, boolean()} - The verbose or {verbose, true} options add some trace flags that fprof does not need, but that can be interesting for general debugging purposes. These options are only allowed with the start option.

cpu_time | {cpu_time, boolean()} - The cpu_time or {cpu_time, true} options make the timestamps in the trace be in CPU time instead of the default wallclock time. These options are only allowed with the start option.

Note

Getting correct values out of cpu_time can be difficult. The best way to get correct values is to run using a single scheduler and bind that scheduler to a specific CPU. For example:

erl +S 1 +sbt db`

{procs, PidSpec} | {procs, [PidSpec]} - Specifies which processes that should be traced. If this option is not given, the calling process is traced. All processes spawned by the traced processes are also traced. This option is only allowed with the start option.

file | {file, Filename} - Specifies the filename of the trace. If the option file is given, or none of these options are given, the file fprof.trace is used. This option is only allowed with the start option, but not with the {tracer, Tracer} option.

{tracer, Tracer} - Specifies that trace to process or port shall be done instead of trace to file. This option is only allowed with the start option, but not with the {file, Filename} option.

trace(What, Value)

-spec trace(start, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
               when Filename :: file:filename(), ServerPid :: pid(), Reason :: term();
           (verbose, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
               when Filename :: file:filename(), ServerPid :: pid(), Reason :: term();
           (OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}
               when OptionName :: atom(), OptionValue :: term(), ServerPid :: pid(), Reason :: term().

Starts or stop tracing.

If What is atom start, this call is equivalent to trace([start, {file, Value}]).

If What is atom verbose, this call is equivalent to trace([start, verbose, {file, Value}]).

If What is a tuple {OptionName, OptionValue}, this call is equivalent to trace([What]).

lcnt

A runtime system Lock Profiling tool.

The lcnt module is used to profile the internal ethread locks in the Erlang Runtime System. With lcnt enabled, internal counters in the runtime system are updated each time a lock is taken. The counters stores information about the number of acquisition tries and the number of collisions that has occurred during the acquisition tries. The counters also record the waiting time a lock has caused for a blocked thread when a collision has occurred.

The data produced by the lock counters will give an estimate on how well the runtime system will behave from a parallelizable view point for the scenarios tested. This tool was mainly developed to help Erlang runtime developers iron out potential and generic bottlenecks.

Locks in the emulator are named after what type of resource they protect and where in the emulator they are initialized, those are lock 'classes'. Most of those locks are also instantiated several times, and given unique identifiers, to increase locking granularity. Typically an instantiated lock protects a disjunct set of the resource, for example ets tables, processes or ports. In other cases it protects a specific range of a resource, for example pix_lock which protects index to process mappings, and is given a unique number within the class. A unique lock in lcnt is referenced by a name (class) and an identifier: {Name, Id}.

Some locks in the system are static and protects global resources, for example bif_timers and the run_queue locks. Other locks are dynamic and not necessarily long lived, for example process locks and ets-table locks. The statistics data from short lived locks can be stored separately when the locks are deleted. This behavior is by default turned off to save memory but can be turned on via lcnt:rt_opt({copy_save, true}). The lcnt:apply/1,2,3 functions enables this behavior during profiling.

See Also

LCNT User's Guide

Summary

Types

category_atom()

lock_counter_data()

option()

print()

sort()

threshold()

Functions

apply(Fun)

Equivalent to apply(Fun, []).

apply(Fun, Args)

Sets up lock counters, applies Fun with Args, and cleans up.

apply(Module, Function, Args)

Equivalent to apply(fun() -> apply(Module, Function, Args) end).

clear()

Equivalent to clear(node()).

clear(Node)

Clears the internal lock statistics from the runtime system.

collect()

Equivalent to collect(node()).

collect(Node)

Collects lock statistics from the runtime system.

conflicts()

Equivalent to conflicts([]).

conflicts(Options)

Prints a list of internal locks and its statistics.

information()

Prints lcnt server state and generic information about collected lock statistics.

inspect(Lock)

Equivalent to inspect(Lock, []).

inspect(Lock, Options)

Prints a list of internal lock counters for a specific lock.

load(Filename)

Restores previously saved data to the server.

locations()

Equivalent to locations([]).

locations(Options)

Prints a list of internal lock counters by source code locations.

pid(Id, Serial)

Equivalent to pid(node(), Id, Serial).

pid(Node, Id, Serial)

Creates a process id with creation 0.

port(Id)

Equivalent to port(node(), Id).

port(Node, Id)

Creates a port id with creation 0.

rt_clear()

Equivalent to rt_clear(node()).

rt_clear(Node)

Clear the internal counters.

rt_collect()

Equivalent to rt_collect(node()).

rt_collect(Node)

Returns a list of raw lock counter data.

rt_mask()

Return the current category mask for the current node.

rt_mask(Arg)

Sets the current lock category mask for the current node or retrieves the current mask for a remote node.

rt_mask(Node, Categories)

Sets the lock category mask according to Categories on node Node.

rt_opt(Option)

Equivalent to rt_opt(node(), {Type, Value}).

rt_opt(Node, Option)

Sets a single option on node Node.

save(Filename)

Saves the collected data to file.

start()

Starts the lock profiler server.

stop()

Stops the lock profiler server.

swap_pid_keys()

Swaps places on Name and Id space for ports and processes.

Types

category_atom()

(not exported) (since OTP R13B04)

-type category_atom() :: atom().

lock_counter_data()

(not exported) (since OTP R13B04)

-type lock_counter_data() :: term().

option()

(not exported) (since OTP R13B04)

-type option() ::
          {sort, Sort :: sort()} |
          {reverse, boolean()} |
          {locations, boolean()} |
          {thresholds, Thresholds :: [threshold()]} |
          {print, PrintOptions :: [print() | {print(), non_neg_integer()}]} |
          {max_locks, MaxLocks :: non_neg_integer() | none} |
          {combine, boolean()}.

print()

(not exported) (since OTP R13B04)

-type print() :: colls | duration | entry | id | name | ratio | time | tries | type.

sort()

(not exported) (since OTP R13B04)

-type sort() :: colls | entry | id | name | ratio | time | tries | type.

threshold()

(not exported) (since OTP R13B04)

-type threshold() :: {colls, non_neg_integer()} | {time, non_neg_integer()} | {tries, non_neg_integer()}.

Functions

apply(Fun)

(since OTP R13B04)

-spec apply(Fun) -> term() when Fun :: fun().

Equivalent to apply(Fun, []).

apply(Fun, Args)

(since OTP R13B04)

-spec apply(Fun, Args) -> term() when Fun :: fun(), Args :: [term()].

Sets up lock counters, applies Fun with Args, and cleans up.

Clears the lock counters and then setups the instrumentation to save all destroyed locks. After setup the function is called, passing the elements in Args as arguments. When the function returns the statistics are immediately collected to the server. After the collection the instrumentation is returned to its previous behavior. The result of the applied function is returned.

Warning

This function should only be used for micro-benchmarks; it sets copy_save to true for the duration of the call, which can quickly lead to running out of memory.

apply(Module, Function, Args)

(since OTP R13B04)

-spec apply(Module, Function, Args) -> term()
               when Module :: module(), Function :: atom(), Args :: [term()].

Equivalent to apply(fun() -> apply(Module, Function, Args) end).

clear()

(since OTP R13B04)

-spec clear() -> ok.

Equivalent to clear(node()).

clear(Node)

(since OTP R13B04)

-spec clear(Node) -> ok when Node :: node().

Clears the internal lock statistics from the runtime system.

This clears the data in the runtime system but not in server. All counters for static locks are zeroed, all dynamic locks currently alive are zeroed and all saved locks now destroyed are removed. It also resets the duration timer.

collect()

(since OTP R13B04)

-spec collect() -> ok.

Equivalent to collect(node()).

collect(Node)

(since OTP R13B04)

-spec collect(Node) -> ok when Node :: node().

Collects lock statistics from the runtime system.

The function starts a server if it is not already started. It then populates the server with lock statistics. If the server held any lock statistics data before the collect then that data is lost.

conflicts()

(since OTP R13B04)

-spec conflicts() -> ok.

Equivalent to conflicts([]).

conflicts(Options)

(since OTP R13B04)

-spec conflicts(Options) -> ok when Options :: [option()].

Prints a list of internal locks and its statistics.

For option description, see lcnt:inspect/2.

information()

(since OTP R13B04)

-spec information() -> ok.

Prints lcnt server state and generic information about collected lock statistics.

inspect(Lock)

(since OTP R13B04)

-spec inspect(Lock) -> ok
                 when
                     Lock :: Name | {Name, Id | [Id]},
                     Name :: atom() | pid() | port(),
                     Id :: atom() | integer() | pid() | port().

Equivalent to inspect(Lock, []).

inspect(Lock, Options)

(since OTP R13B04)

-spec inspect(Lock, Options) -> ok
                 when
                     Lock :: Name | {Name, Id | [Id]},
                     Name :: atom() | pid() | port(),
                     Id :: atom() | integer() | pid() | port(),
                     Options :: [option()].

Prints a list of internal lock counters for a specific lock.

Lock Name and Id for ports and processes are interchangeable with the use of lcnt:swap_pid_keys/0 and is the reason why pid/0 and port/0 options can be used in both Name and Id space. Both pids and ports are special identifiers with stripped creation and can be recreated with lcnt:pid/2,3 and lcnt:port/1,2.

Option description:

{combine, boolean()} - Combine the statistics from different instances of a lock class.
Default: true

{locations, boolean()} - Print the statistics by source file and line numbers.
Default: false

{max_locks, MaxLocks} - Maximum number of locks printed or no limit with none.
Default: 20

{print, PrintOptions} - Printing options:

name - Named lock or named set of locks (classes). The same name used for initializing the lock in the VM.

id - Internal id for set of locks, not always unique. This could be table name for ets tables (db_tab), port id for ports, integer identifiers for allocators, etc.

type - Type of lock: rw_mutex, mutex, spinlock, rw_spinlock or proclock.

entry - In combination with {locations, true} this option prints the lock operations source file and line number entry-points along with statistics for each entry.

tries - Number of acquisitions of this lock.

colls - Number of collisions when a thread tried to acquire this lock. This is when a trylock is EBUSY, a write try on read held rw_lock, a try read on write held rw_lock, a thread tries to lock an already locked lock. (Internal states supervises this.)

ratio - The ratio between the number of collisions and the number of tries (acquisitions) in percentage.

time - Accumulated waiting time for this lock. This could be greater than actual wall clock time, it is accumulated for all threads. Trylock conflicts does not accumulate time.

duration - Percentage of accumulated waiting time of wall clock time. This percentage can be higher than 100% since accumulated time is from all threads.

Default: [name,id,tries,colls,ratio,time,duration]

{reverse, boolean()} - Reverses the order of sorting.
Default: false

{sort, Sort} - Column sorting orders.
Default: time

{thresholds, Thresholds} - Filtering thresholds. Anything values above the threshold value are passed through.
Default: [{tries, 0}, {colls, 0}, {time, 0}]

load(Filename)

(since OTP R13B04)

-spec load(Filename) -> ok when Filename :: file:filename().

Restores previously saved data to the server.

locations()

(since OTP R13B04)

-spec locations() -> ok.

Equivalent to locations([]).

locations(Options)

(since OTP R13B04)

-spec locations(Options) -> ok when Options :: [option()].

Prints a list of internal lock counters by source code locations.

For option description, see lcnt:inspect/2.

pid(Id, Serial)

(since OTP R13B04)

-spec pid(Id, Serial) -> pid() when Id :: integer(), Serial :: integer().

Equivalent to pid(node(), Id, Serial).

pid(Node, Id, Serial)

(since OTP R13B04)

-spec pid(Node, Id, Serial) -> pid() when Node :: node(), Id :: integer(), Serial :: integer().

Creates a process id with creation 0.

port(Id)

(since OTP R13B04)

-spec port(Id) -> port() when Id :: integer().

Equivalent to port(node(), Id).

port(Node, Id)

(since OTP R13B04)

-spec port(Node, Id) -> port() when Node :: node(), Id :: integer().

Creates a port id with creation 0.

rt_clear()

(since OTP R13B04)

-spec rt_clear() -> ok.

Equivalent to rt_clear(node()).

rt_clear(Node)

(since OTP R13B04)

-spec rt_clear(Node) -> ok when Node :: node().

Clear the internal counters.

Equivalent to lcnt:clear(Node).

rt_collect()

(since OTP R13B04)

-spec rt_collect() -> [lock_counter_data()].

Equivalent to rt_collect(node()).

rt_collect(Node)

(since OTP R13B04)

-spec rt_collect(Node) -> [lock_counter_data()] when Node :: node().

Returns a list of raw lock counter data.

rt_mask()

(since OTP 20.1)

-spec rt_mask() -> [category_atom()].

Return the current category mask for the current node.

rt_mask(Arg)

(since OTP 20.1)

-spec rt_mask(Node) -> [category_atom()] when Node :: node();
             (Categories) -> ok | {error, copy_save_enabled} when Categories :: [category_atom()].

Sets the current lock category mask for the current node or retrieves the current mask for a remote node.

If Arg is an atom, it is assumed to be a node, and this call returns the current lock category mask for node Arg.

If Arg is a list, this call is equivalent to rt_mask(node(), Arg).

rt_mask(Node, Categories)

(since OTP 20.1)

-spec rt_mask(Node, Categories) -> ok | {error, copy_save_enabled}
                 when Node :: node(), Categories :: [category_atom()].

Sets the lock category mask according to Categories on node Node.

This call will fail if the copy_save option is enabled; see lcnt:rt_opt/2.

Valid categories are:

allocator

db (ETS tables)

debug

distribution

generic

io

process

scheduler

This list is subject to change at any time, as is the category any given lock belongs to.

rt_opt(Option)

(since OTP R13B04)

-spec rt_opt(Option) -> boolean()
                when Option :: {Type, Value :: boolean()}, Type :: copy_save | process_locks.

Equivalent to rt_opt(node(), {Type, Value}).

rt_opt(Node, Option)

(since OTP R13B04)

-spec rt_opt(Node, Option) -> boolean()
                when
                    Node :: node(),
                    Option :: {Type, Value :: boolean()},
                    Type :: copy_save | process_locks.

Sets a single option on node Node.

Option description:

{copy_save, boolean()} - Retains the statistics of destroyed locks.
Default: false

Warning

This option will use a lot of memory when enabled, which must be reclaimed with lcnt:rt_clear/0,1. Note that it makes no distinction between locks that were destroyed and locks for which counting was disabled, so enabling this option will disable changes to the lock category mask.

{process_locks, boolean()} - Profile process locks, equal to adding process to the lock category mask; see lcnt:rt_mask/2.
Default: true

save(Filename)

(since OTP R13B04)

-spec save(Filename) -> ok when Filename :: file:filename().

Saves the collected data to file.

start()

(since OTP R13B04)

-spec start() -> {ok, Pid} | {error, {already_started, Pid}} when Pid :: pid().

Starts the lock profiler server.

The server only act as a medium for the user and performs filtering and printing of data collected by lcnt:collect/1.

stop()

(since OTP R13B04)

-spec stop() -> ok.

Stops the lock profiler server.

swap_pid_keys()

(since OTP R13B04)

-spec swap_pid_keys() -> ok.

Swaps places on Name and Id space for ports and processes.

make

A Make Utility for Erlang

The module make provides a set of functions similar to the UNIX type Make functions.

Emakefile

make:all/0,1 and make:files/1,2 first looks for {emake, Emake} in options, then in the current working directory for a file named Emakefile. If present Emake should contain elements like this:

Modules.
{Modules,Options}.

Modules is an atom or a list of atoms. It can be

a module name, for exmaple, file1

a module name in another directory, for exmaple, '../foo/file3'

a set of modules specified with a wildcards, for exmaple, 'file*'

a wildcard indicating all modules in current directory, that is: '*'

a list of any of the above, for exmaple, ['file*','../foo/file3','File4']

Options is a list of compiler options.

Emakefile is read from top to bottom. If a module matches more than one entry, the first match is used. For example, the following Emakefile means that file1 should be compiled with the options [debug_info,{i,"../foo"}], while all other files in the current directory should be compiled with only the debug_info flag.

{'file1',[debug_info,{i,"../foo"}]}.
{'*',[debug_info]}.

See Also

The Compiler Application

Summary

Functions

all()

Equivalent to all([]).

all(Options)

This function determines the set of modules to compile and the compile options to use, by first looking for the emake make option, if not present reads the configuration from a file named Emakefile (see below). If no such file is found, the set of modules to compile defaults to all modules in the current working directory.

files(ModFiles)

Equivalent to files(ModFiles, []).

files(ModFiles, Options)

This function does exactly the same thing as all/0,1, but for the specified ModFiles, which is a list of module or file names.

Functions

all()

-spec all() -> up_to_date | error.

Equivalent to all([]).

all(Options)

-spec all(Options) -> up_to_date | error
             when
                 Options :: [Option],
                 Option :: noexec | load | netload | {emake, Emake} | compile:option(),
                 Emake :: [EmakeElement],
                 EmakeElement :: Modules | {Modules, [compile:option()]},
                 Modules :: atom() | [atom()].

This function determines the set of modules to compile and the compile options to use, by first looking for the emake make option, if not present reads the configuration from a file named Emakefile (see below). If no such file is found, the set of modules to compile defaults to all modules in the current working directory.

Traversing the set of modules, it then recompiles every module for which at least one of the following conditions apply:

there is no object file, or

the source file has been modified since it was last compiled, or,

an include file has been modified since the source file was last compiled.

As a side effect, the function prints the name of each module it tries to compile. If compilation fails for a module, the make procedure stops and error is returned.

Options is a list of options for make and the Erlang compiler. The following make options exist:

noexec No execution mode. Just prints the name of each module that needs to be compiled.

load Load mode. Loads all recompiled modules.

netload Net load mode. Loads all recompiled modules on all known nodes.

{emake, Emake} Rather than reading the Emakefile specify configuration explicitly.

All items in Options that are not make options are assumed to be compiler options and are passed as-is to compile:file/2.

files(ModFiles)

-spec files(ModFiles) -> up_to_date | error
               when ModFiles :: [(Module :: module()) | (File :: file:filename())].

Equivalent to files(ModFiles, []).

files(ModFiles, Options)

-spec files(ModFiles, Options) -> up_to_date | error
               when
                   ModFiles :: [(Module :: module()) | (File :: file:filename())],
                   Options :: [Option],
                   Option :: noexec | load | netload | compile:option().

This function does exactly the same thing as all/0,1, but for the specified ModFiles, which is a list of module or file names.

The file extension .erl can be omitted.

The Emakefile (if it exists) in the current directory is searched for compiler options for each module. If a given module does not exist in Emakefile or if Emakefile does not exist, the module is still compiled.

tags

Generate Emacs TAGS file from Erlang source files

A TAGS file is used by Emacs to find function and variable definitions in any source file in large projects. This module can generate a TAGS file from Erlang source files. It recognises functions, records, and macro definitions.

Options

The functions in this module have an optional argument Options. It is a list which can contain the following elements:

{outfile, NameOfTAGSFile} Create a TAGS file named NameOfTAGSFile.

{outdir, NameOfDirectory} Create a file named TAGS in the directory NameOfDirectory.

The default behaviour is to create a file named TAGS in the current directory.

Examples

tags:root([{outfile, "root.TAGS"}]).

This command will create a file named root.TAGS in the current directory. The file will contain references to all Erlang source files in the Erlang distribution.

tags:files(["foo.erl", "bar.erl", "baz.erl"], [{outdir, "../projectdir"}]).

This command will create a file named TAGS placed it in the directory ../projectdir. The file contains information about the functions, records, and macro definitions of the three files.

See Also

Richard M. Stallman. GNU Emacs Manual, chapter "Editing Programs", section "Tag Tables". Free Software Foundation, 1995.

Anders Lindgren. The Erlang editing mode for Emacs. Ericsson, 1998.

Summary

Types

option()

Functions

dir(Dir)

Equivalent to dir(Dir, []).

dir(Dir, Options)

Create a TAGS file for all files in directory Dir.

dirs(DirList)

Equivalent to dirs(Dirs, []).

dirs(DirList, Options)

Create a TAGS file for all files in any directory in DirList.

file(File)

Equivalent to file(Name, []).

file(File, Options)

Create a TAGS file for the file File.

files(FileList)

Equivalent to files(Files, []).

files(FileList, Options)

Create a TAGS file for the files in the list FileList.

root()

Equivalent to root([]).

root(Options)

Create a TAGS file covering all files in the Erlang distribution.

subdir(Dir)

Equivalent to subdir(Dir, []).

subdir(Dir, Options)

Descend recursively into the directory Dir and create a TAGS file based on all files found.

subdirs(DirList)

Equivalent to subdirs(Dirs, []).

subdirs(DirList, Options)

Descend recursively into the directories in DirList and create a TAGS file based on all files found.

Types

option()

(not exported)

-type option() ::
          {outfile, NameOfTAGSFile :: file:filename()} | {outdir, NameOfDirectory :: file:filename()}.

Functions

dir(Dir)

-spec dir(Dir) -> ok | error when Dir :: file:filename().

Equivalent to dir(Dir, []).

dir(Dir, Options)

-spec dir(Dir, Options) -> ok | error when Dir :: file:filename(), Options :: [option()].

Create a TAGS file for all files in directory Dir.

dirs(DirList)

-spec dirs(DirList) -> ok | error when DirList :: [file:filename()].

Equivalent to dirs(Dirs, []).

dirs(DirList, Options)

-spec dirs(DirList, Options) -> ok | error when DirList :: [file:filename()], Options :: [option()].

Create a TAGS file for all files in any directory in DirList.

file(File)

-spec file(File) -> ok | error when File :: file:filename().

Equivalent to file(Name, []).

file(File, Options)

-spec file(File, Options) -> ok | error when File :: file:filename(), Options :: [option()].

Create a TAGS file for the file File.

files(FileList)

-spec files(FileList) -> ok | error when FileList :: [file:filename()].

Equivalent to files(Files, []).

files(FileList, Options)

-spec files(FileList, Options) -> ok | error when FileList :: [file:filename()], Options :: [option()].

Create a TAGS file for the files in the list FileList.

root()

-spec root() -> ok | error.

Equivalent to root([]).

root(Options)

-spec root(Options) -> ok | error when Options :: [option()].

Create a TAGS file covering all files in the Erlang distribution.

subdir(Dir)

-spec subdir(Dir) -> ok | error when Dir :: file:filename().

Equivalent to subdir(Dir, []).

subdir(Dir, Options)

-spec subdir(Dir, Options) -> ok | error when Dir :: file:filename(), Options :: [option()].

Descend recursively into the directory Dir and create a TAGS file based on all files found.

subdirs(DirList)

-spec subdirs(DirList) -> ok | error when DirList :: [file:filename()].

Equivalent to subdirs(Dirs, []).

subdirs(DirList, Options)

-spec subdirs(DirList, Options) -> ok | error when DirList :: [file:filename()], Options :: [option()].

Descend recursively into the directories in DirList and create a TAGS file based on all files found.

tprof

Process Tracing Profiling Tool

tprof provides convenience helpers for Erlang process profiling using the trace BIFs.

Warning

This module aims to replace eprof and cprof into a unified API for measuring call count, time, and allocation. It is experimental in Erlang/OTP 27.0.

It is possible to analyze the number of calls, the time spent by function, and heap allocations by function. Profiling can be done ad-hoc or run in a server-aided mode for deeper introspection of the code running in production. The server-aided mode can be run using the default tprof server or an isolated server/0 started through start(#{ session => atom() }).

There are three kinds of profiling supported by this module:

call_count

call_time

call_memory

The default is call_count, which has the smallest performance impact and memory footprint, but it does not support per-process profiling. For this reason, all of the examples below uses call_memory, which measures heap allocation, and provide a more complex feature set to demonstrate.

Erlang terms that do not fit in a single machine word are allocated on the process heap. For example, a function returning a tuple of two elements needs to allocate the tuple on the process heap. The actual consumption is three words, because the runtime systems also need an extra word to store the tuple size.

Note

Expect a slowdown in the program execution when profiling is enabled.

For profiling convenience, measurements are accumulated for functions that are not enabled in some trace pattern. Consider this call stack example:

top_traced_function(...)
not_traced_function()
bottom_traced_function()

Allocations that happened within not_traced_function will be added to the allocations for top_traced_function. However, allocations that occurred within bottom_traced_function are not included in the top_traced_function. To only keep track of each function own allocations, it is necessary to trace all functions.

Warning

Avoid hot code reloading for modules participating in the tracing. Reloading a module disables tracing and discards the accumulated statistics. The tprof results will probably be incorrect when the profiled code was reloading during a profiling session.

Ad-hoc profiling

Ad-hoc profiling is convenient for profiling a single function call.

For example:

1> tprof:profile(lists, seq, [1, 16], #{type => call_memory}).

****** Process <0.92.0>  --  100.00% of total ***
FUNCTION          CALLS  WORDS  PER CALL  [     %]
lists:seq_loop/3      5     32      6.40  [100.00]
                            32            [ 100.0]
ok

By default tracing is enabled for all functions in all modules. When funs are created in the interactive shell, parts of shell code are also traced:

1> tprof:profile(fun() -> lists:seq(1, 16) end, #{type => call_memory}).

****** Process <0.95.0>  --  100.00% of total ***
FUNCTION                   CALLS  WORDS  PER CALL  [    %]
erl_eval:do_apply/7            1      3      3.00  [ 3.61]
erl_eval:match_list/6          1      3      3.00  [ 3.61]
lists:reverse/1                1      4      4.00  [ 4.82]
erl_eval:expr_list/7           3      7      2.33  [ 8.43]
erl_eval:ret_expr/3            4     16      4.00  [19.28]
erl_eval:merge_bindings/4      3     18      6.00  [21.69]
lists:seq_loop/3               5     32      6.40  [38.55]
                                     83            [100.0]
ok

However, it is possible to limit the trace to specific functions or modules:

2> tprof:profile(fun() -> lists:seq(1, 16) end,
                 #{type => call_memory, pattern => [{lists, seq_loop, '_'}]}).
****** Process <0.98.0>  --  100.00% of total ***
FUNCTION          CALLS  WORDS  PER CALL  [     %]
lists:seq_loop/3      5     32      6.40  [100.00]
                            32            [ 100.0]

ok

Ad-hoc profiling results can be printed in a few different ways. The following examples use the test module defined like this:

-module(test).
-export([test_spawn/0]).
test_spawn() ->
    {Pid, MRef} = spawn_monitor(fun () -> lists:seq(1, 32) end),
    receive
        {'DOWN', MRef, process, Pid, normal} ->
            done
    end.

By default per-process statistics is shown:

1> tprof:profile(test, test_spawn, [], #{type => call_memory}).

****** Process <0.176.0>    -- 23.66 % of total allocations ***
FUNCTION                CALLS  WORDS  PER CALL  [    %]
erlang:spawn_monitor/1      1      2         2  [ 9.09]
erlang:spawn_opt/4          1      6         6  [27.27]
test:test_spawn/0           1     14        14  [63.64]
                                  22            [100.0]

****** Process <0.177.0>    -- 76.34 % of total allocations ***
FUNCTION           CALLS  WORDS  PER CALL  [    %]
erlang:apply/2         1      7         7  [ 9.86]
lists:seq_loop/3       9     64         7  [90.14]
                             71            [100.0]

The following example prints the combined memory allocation of all processes, sorted by the total number of allocated words in descending order:

2> tprof:profile(test, test_spawn, [],
                 #{type => call_memory, report => {total, {measurement, descending}}}).

FUNCTION                CALLS  WORDS  PER CALL  [    %]
lists:seq_loop/3            9     64         7  [68.82]
test:test_spawn/0           1     14        14  [15.05]
erlang:apply/2              1      7         7  [ 7.53]
erlang:spawn_opt/4          1      6         6  [ 6.45]
erlang:spawn_monitor/1      1      2         2  [ 2.15]
                                  93            [100.0]

The profiling data can also be collected for further inspection:

3> {done, ProfileData} = tprof:profile(fun test:test_spawn/0,
                                       #{type => call_memory, report => return}).
<...>
4> tprof:format(tprof:inspect(ProfileData, process, {percent, descending})).

****** Process <0.223.0>    -- 23.66 % of total allocations ***
FUNCTION                CALLS  WORDS  PER CALL  [    %]
test:test_spawn/0           1     14        14  [63.64]
erlang:spawn_opt/4          1      6         6  [27.27]
erlang:spawn_monitor/1      1      2         2  [ 9.09]
                                  22            [100.0]

****** Process <0.224.0>    -- 76.34 % of total allocations ***
FUNCTION           CALLS  WORDS  PER CALL  [    %]
lists:seq_loop/3       9     64         7  [90.14]
erlang:apply/2         1      7         7  [ 9.86]
                             71            [100.0]

Which processes that are profiled depends on the profiling type.

call_count (default) counts calls in all processes.

call_time and call_memory limits the profiling to the processes spawned from the user-provided function (using the set_on_spawn option for trace:process/4).

call_time and call_memory can be restricted to profile a single process:

2> tprof:profile(test, test_spawn, [],
                 #{type => call_memory, set_on_spawn => false}).

****** Process <0.183.0>    -- 100.00 % of total allocations ***
FUNCTION                CALLS  WORDS  PER CALL  [    %]
erlang:spawn_monitor/1      1      2         2  [ 9.09]
erlang:spawn_opt/4          1      6         6  [27.27]
test:test_spawn/0           1     14        14  [63.64]

Erlang programs can perform expensive operations in other processes than the original one. You can include multiple, new, or even all processes in the trace when measuring time or memory:

7> pg:start_link().
{ok,<0.252.0>}
8> tprof:profile(fun() -> pg:join(group, self()) end,
                 #{type => call_memory, rootset => [pg]}).
****** Process <0.252.0>    -- 52.86 % of total allocations ***
FUNCTION                      CALLS  WORDS  PER CALL  [    %]
pg:leave_local_update_ets/5       1      2         2  [ 1.80]
gen:reply/2                       1      3         3  [ 2.70]
erlang:monitor/2                  1      3         3  [ 2.70]
gen_server:try_handle_call/4      1      3         3  [ 2.70]
gen_server:try_dispatch/4         1      3         3  [ 2.70]
maps:iterator/1                   2      4         2  [ 3.60]
maps:take/2                       1      6         6  [ 5.41]
pg:join_local_update_ets/5        1      8         8  [ 7.21]
pg:handle_info/2                  1      8         8  [ 7.21]
pg:handle_call/3                  1      9         9  [ 8.11]
gen_server:loop/7                 2      9         4  [ 8.11]
ets:lookup/2                      2     10         5  [ 9.01]
pg:join_local/3                   1     11        11  [ 9.91]
pg:notify_group/5                 2     16         8  [14.41]
erlang:setelement/3               2     16         8  [14.41]
                                       111            [100.0]

****** Process <0.255.0>    -- 47.14 % of total allocations ***
FUNCTION                   CALLS  WORDS  PER CALL  [    %]
erl_eval:match_list/6          1      3         3  [ 3.03]
erlang:monitor/2               1      3         3  [ 3.03]
lists:reverse/1                2      4         2  [ 4.04]
pg:join/3                      1      4         4  [ 4.04]
erl_eval:add_bindings/2        1      5         5  [ 5.05]
erl_eval:do_apply/7            2      6         3  [ 6.06]
gen:call/4                     1      8         8  [ 8.08]
erl_eval:expr_list/7           4     10         2  [10.10]
gen:do_call/4                  1     16        16  [16.16]
erl_eval:ret_expr/3            4     16         4  [16.16]
erl_eval:merge_bindings/4      3     24         8  [24.24]
                                     99            [100.0]

By default, there is no limit for the profiling time. For ad-hoc profiling, it is possible to configure a time limit. If the profiled function does not return before that time expires, the process is terminated with reason kill. Any unlinked children processes started by the user-supplied function are kept; it is the responsibility of the developer to take care of such processes.

9> tprof:profile(timer, sleep, [100000], #{timeout => 1000}).

By default, only one ad-hoc or server-aided profiling session is allowed at any point in time. It is possible to force multiple ad-hoc sessions concurrently, but it is the responsibility of the developer to ensure that trace patterns do not overlap:

1> tprof:profile(fun() -> lists:seq(1, 32) end,
    #{registered => false, pattern => [{lists, '_', '_'}]}).

Server-aided profiling

Server-aided profiling can be done on a system that is up and running. To do that, start the tprof server, and then add trace patterns and processes to trace while the system handles actual traffic. Data can extracted, inspected, and printed at any time. The following example traces activity of all processes supervised by the Kernel supervisor:

1> tprof:start(#{type => call_memory}).
{ok,<0.200.0>}
2> tprof:enable_trace({all_children, kernel_sup}).
34
3> tprof:set_pattern('_', '_' , '_').
16728
4> Sample = tprof:collect().
{call_memory,
    [{gen_server,try_dispatch,4,[{<0.154.0>,2,6}]},
     {erlang,iolist_to_iovec,1,[{<0.161.0>,1,8}]},
<...>
5 > tprof:format(tprof:inspect(Sample)).

****** Process <0.154.0>    -- 14.21 % of total allocations ***
FUNCTION                   CALLS  WORDS  PER CALL  [    %]
maps:iterator/1                2      4         2  [15.38]
gen_server:try_dispatch/4      2      6         3  [23.08]
net_kernel:handle_info/2       2     16         8  [61.54]
                                     26            [100.0]

****** Process <0.161.0>    -- 85.79 % of total allocations ***
FUNCTION                        CALLS  WORDS  PER CALL  [    %]
disk_log:handle/2                   2      2         1  [ 1.27]
disk_log_1:maybe_start_timer/1      1      3         3  [ 1.91]
disk_log_1:mf_write_cache/1         1      3         3  [ 1.91]
<...>

It is possible to profile the entire running system, and then examine individual processes:

1> tprof:start(#{type => call_memory}).
2> tprof:enable_trace(all), tprof:set_pattern('_', '_' , '_').
9041
3> timer:sleep(10000), tprof:disable_trace(all), Sample = tprof:collect().
{call_memory,
    [{user_drv,server,3,[{<0.64.0>,12,136}]},
     {user_drv,contains_ctrl_g_or_ctrl_c,1,[{<0.64.0>,80,10}]},
<...>
4> Inspected = tprof:inspect(Sample, process, measurement), Shell = maps:get(self(), Inspected).
{call_memory, 2743,
    [{shell,{enc,0},1,2,2,0.07291286912139992},
<...>
5> tprof:format(Shell).

FUNCTION                           CALLS  WORDS  PER CALL  [    %]
<...>
erl_lint:start/2                       2    300       150  [10.94]
shell:used_records/1                 114    342         3  [12.47]

Summary

Types

column()

Column to sort by inspect/3 or profile/4.

process()

A process identifier (pid) or a registered process name.

profile_line()

Inspected data for a single function of the specified Module.

profile_options()

Ad-hoc profiler options; see profile/4.

profile_result()

Profile of a single process, or combined profile of multiple processes, sorted by a selected column.

rootset()

server()

A tprof server.

sort_by()

start_options()

trace_info()

Raw data extracted from tracing BIFs.

trace_map()

Traced functions (with their arities) grouped by module name, or all if all code is traced.

trace_options()

Options for enabling profiling of the selected processes; see enable_trace/2.

trace_pattern()

trace_type()

The type of profiling that the tprof server will do.

Functions

clear_pattern(Mod, Fun, Arity)

Disables tracing functions matching the supplied pattern.

clear_pattern(Server, Mod, Fun, Arity)

Equivalent to clear_pattern(Mod, Fun, Arity) but uses the provided Server.

collect()

Returns statistics for current trace map.

collect(Server)

Equivalent to collect/0 but uses the provided Server.

continue()

Resumes previously paused profiling.

continue(Server)

Equivalent to continue/0 but uses the provided Server.

disable_trace(Rootset)

Equivalent to disable_trace(Spec, #{set_on_spawn => true}).

disable_trace(Spec, Options)

Stops accumulating traces for specified processes.

disable_trace(Server, Spec, Options)

enable_trace(Rootset)

Equivalent to enable_trace(Spec, #{set_on_spawn => true}).

enable_trace(Spec, Options)

Similar to trace:process/4, but supports a few more options for tracing convenience.

enable_trace(Server, Spec, Options)

Equivalent to enable_trace/2 but uses the provided Server.

format(Inspected)

Formats profile data transformed with inspect/3, outputting to the default output device.

format(IoDevice, Inspected)

Formats profile transformed with inspect/3, outputting to device IoDevice.

get_trace_map()

Returns a map of module names to functions with their arities.

get_trace_map(Server)

Equivalent to get_trace_map/0 but uses the provided Server.

inspect(Profile)

Equivalent to inspect(Profile, process, percent).

inspect(Profile, Type, SortBy)

Transforms raw data returned by tracing BIFs into a form convenient for subsequent analysis and formatting.

pause()

Pauses trace collection for all currently traced functions, retaining existing traces.

pause(Server)

Equivalent to pause/0 but uses the provided Server.

profile(Fun)

Equivalent to profile(Fun, #{}).

profile(Fun, Options)

Does ad-hoc profiling of the call Fun().

profile(Module, Function, Args)

Equivalent to profile(Module, Function, Args, #{}).

profile(Module, Function, Args, Options)

Does ad-hoc profiling for the call apply(Module, Function, Args).

restart()

Clears accumulated profiles and starts profiling if it was paused.

restart(Server)

Equivalent to restart/0 but uses the provided Server.

set_pattern(Mod, Fun, Arity)

Enables tracing for all functions matching the supplied pattern.

set_pattern(Server, Mod, Fun, Arity)

Equivalent to set_pattern/3 but uses the provided Server.

start()

Equivalent to start(#{}).

start(Config)

Starts the server, not supervised.

start_link()

Equivalent to start_link(#{}).

start_link(Config)

Equivalent to start/1 but also links the profiling server to the caller.

stop()

Stops the default tprof server and disable tracing enabled by the server.

stop(Server)

Equivalent to stop/0 but uses the provided Server.

Types

column()

(not exported) (since OTP 27.0)

-type column() :: module | function | calls | measurement | measurement_per_call | percent.

Column to sort by inspect/3 or profile/4.

module - Module name.

function - Function name.

calls - Number of calls to the function.

measurement - Total measurement (call count, time, or heap allocation) throughout all calls to the function.

measurement_per_call - Measurement (call count, time, or heap allocation) on average per function call.

percent - Percentage of measurement to total amount during the entire profile collection.

process()

(not exported) (since OTP 27.0)

-type process() :: pid() | atom().

A process identifier (pid) or a registered process name.

profile_line()

(not exported) (since OTP 27.0)

-type profile_line() ::
          {module(),
           Function :: {atom(), arity()},
           Count :: pos_integer(),
           Measurement :: pos_integer(),
           MeasurementPerCall :: non_neg_integer(),
           Percent :: float()}.

Inspected data for a single function of the specified Module.

profile_options()

(not exported) (since OTP 27.0)

-type profile_options() ::
          #{type => trace_type(),
            timeout => timeout(),
            pattern => trace_pattern() | [trace_pattern()],
            set_on_spawn => boolean(),
            rootset => rootset(),
            report => return | process | total | {process, sort_by()} | {total, sort_by()},
            device => io:device()}.

Ad-hoc profiler options; see profile/4.

profile_result()

(not exported) (since OTP 27.0)

-type profile_result() :: {trace_type(), TotalMeasurement :: non_neg_integer(), [profile_line()]}.

Profile of a single process, or combined profile of multiple processes, sorted by a selected column.

rootset()

(not exported) (since OTP 27.0)

-type rootset() :: [process()] | all | existing | new.

server()

(not exported) (since OTP 27.0)

-type server() :: pid() | tprof.

A tprof server.

Each server uses a separate trace:session/0 in order to keep profiling isolated.

sort_by()

(not exported) (since OTP 27.0)

-type sort_by() :: column() | {column(), ascending} | {column(), descending}.

start_options()

(not exported) (since OTP 27.0)

-type start_options() :: #{type => trace_type(), session => atom()}.

trace_info()

(not exported) (since OTP 27.0)

-type trace_info() ::
          {module(),
           Fun :: atom(),
           Arity :: non_neg_integer(),
           [{pid(), Count :: pos_integer(), Measurement :: pos_integer()}]}.

Raw data extracted from tracing BIFs.

trace_map()

(not exported) (since OTP 27.0)

-type trace_map() :: #{module() => [{Fun :: atom(), arity()}]} | all.

Traced functions (with their arities) grouped by module name, or all if all code is traced.

trace_options()

(not exported) (since OTP 27.0)

-type trace_options() :: #{set_on_spawn => boolean()}.

Options for enabling profiling of the selected processes; see enable_trace/2.

trace_pattern()

(not exported) (since OTP 27.0)

-type trace_pattern() :: {module(), Fun :: atom(), arity() | '_'}.

trace_type()

(not exported) (since OTP 27.0)

-type trace_type() :: call_count | call_time | call_memory.

The type of profiling that the tprof server will do.

call_count - Counts the number of calls made to functions. This is a global profiling event that cannot be limited to specific processes. See call_count in trace:function/4 for more details.

call_time - Counts the accumulated time spent in functions. See call_time in trace:function/4 for more details.

call_memory - Counts the accumulated memory allocated in functions. See call_memory in trace:function/4 for more details.

Functions

clear_pattern(Mod, Fun, Arity)

(since OTP 27.0)

-spec clear_pattern(module(), atom(), arity() | '_') -> ok.

Disables tracing functions matching the supplied pattern.

1> tprof:set_pattern(lists, seq, '_').
2
2> tprof:clear_pattern(lists, seq, 3).
1
3> tprof:get_trace_map().
#{lists => [{seq,2}]}

Requires that the default tprof server has been started.

clear_pattern(Server, Mod, Fun, Arity)

(since OTP 27.0)

-spec clear_pattern(server(), module(), atom(), arity() | '_') -> ok.

Equivalent to clear_pattern(Mod, Fun, Arity) but uses the provided Server.

collect()

(since OTP 27.0)

-spec collect() -> {trace_type(), [trace_info()]}.

Returns statistics for current trace map.

collect(Server)

(since OTP 27.0)

-spec collect(server()) -> {trace_type(), [trace_info()]}.

Equivalent to collect/0 but uses the provided Server.

continue()

(since OTP 27.0)

-spec continue() -> ok | not_paused.

Resumes previously paused profiling.

continue(Server)

(since OTP 27.0)

-spec continue(server()) -> ok | not_paused.

Equivalent to continue/0 but uses the provided Server.

disable_trace(Rootset)

(since OTP 27.0)

-spec disable_trace(Spec) -> non_neg_integer()
                       when Spec :: pid() | all | new | existing | {children | all_children, process()};
                   ([process()]) -> non_neg_integer() | {non_neg_integer(), [process()]}.

Equivalent to disable_trace(Spec, #{set_on_spawn => true}).

disable_trace(Spec, Options)

(since OTP 27.0)

-spec disable_trace(Spec, trace_options()) -> non_neg_integer()
                       when Spec :: pid() | all | new | existing | {children | all_children, process()};
                   ([process()], trace_options()) ->
                       non_neg_integer() | {non_neg_integer(), [process()]}.

Stops accumulating traces for specified processes.

See enable_trace/2 for a description of the options.

The profile data accumulated before the process is removed from the traced list is retained. This makes it possible to enable tracing for many or all processes in the system, sleep for a short period of time, then disable tracing for all processes (to avoid system overload), but keeping profile data.

disable_trace(Server, Spec, Options)

(since OTP 27.0)

-spec disable_trace(server(), Spec, trace_options()) -> non_neg_integer()
                       when Spec :: pid() | all | new | existing | {children | all_children, process()};
                   (server(), [process()], trace_options()) ->
                       non_neg_integer() | {non_neg_integer(), [process()]}.

enable_trace(Rootset)

(since OTP 27.0)

-spec enable_trace(Spec) -> non_neg_integer()
                      when Spec :: pid() | all | new | existing | {children | all_children, process()};
                  ([process()]) -> non_neg_integer() | {non_neg_integer(), [process()]}.

Equivalent to enable_trace(Spec, #{set_on_spawn => true}).

enable_trace(Spec, Options)

(since OTP 27.0)

-spec enable_trace(Spec, trace_options()) -> Traced :: non_neg_integer()
                      when Spec :: pid() | all | new | existing;
                  (Spec, trace_options()) ->
                      Traced :: non_neg_integer() | {Traced :: non_neg_integer(), Failed :: [process()]}
                      when Spec :: [process()] | {children | all_children, process()}.

Similar to trace:process/4, but supports a few more options for tracing convenience.

Tracing per process is not supported by call_count profilers.

Spec is either a process identifier (pid) for a local process, one of the following atoms, or a list of local process identifiers or their registered names:

all - All currently existing processes and all that will be created in the future.

existing - All currently existing processes.

new - All processes that will be created in the future.

children - All currently running processes that were directly spawned by the specified process. This mode is helpful for tracing workers of a single supervisor.

all_children - All currently running processes that were spawned by the specified process, or any recursive descendant of it. This mode is designed to facilitate tracing of supervision trees.

Returns the number of processes for which tracing was enabled.

When a list of pids, children or all_children is used, the processes that tracing failed to be enabled on will also be returned. Tracing can fail to be enabled if the process has terminated before tracing could be enabled.

Note

The profiling server does not keep track of processes that were added to the tracing set. It is permitted to stop the profiling server (wiping out any accumulated data), restart the server, set entirely different tracing pattern keeping the list of traced processes for future use. Use disable_trace(Processes) to clear the list of traced processes.

Specify Options to modify tracing behavior:

set_on_spawn - Automatically start tracing for processes spawned by the traced process. On by default.

enable_trace(Server, Spec, Options)

(since OTP 27.0)

-spec enable_trace(server(), Spec, trace_options()) -> non_neg_integer()
                      when Spec :: pid() | all | new | existing | {children | all_children, process()};
                  (server(), [process()], trace_options()) ->
                      non_neg_integer() | {non_neg_integer(), [process()]}.

Equivalent to enable_trace/2 but uses the provided Server.

format(Inspected)

(since OTP 27.0)

-spec format(profile_result() | #{pid() | all => profile_result()}) -> ok.

Formats profile data transformed with inspect/3, outputting to the default output device.

format(IoDevice, Inspected)

(since OTP 27.0)

-spec format(io:device(), profile_result() | #{pid() | all => profile_result()}) -> ok.

Formats profile transformed with inspect/3, outputting to device IoDevice.

get_trace_map()

(since OTP 27.0)

-spec get_trace_map() -> trace_map().

Returns a map of module names to functions with their arities.

get_trace_map(Server)

(since OTP 27.0)

-spec get_trace_map(server()) -> trace_map().

Equivalent to get_trace_map/0 but uses the provided Server.

inspect(Profile)

(since OTP 27.0)

-spec inspect({trace_type(), [trace_info()]}) -> #{all => profile_result()}.

Equivalent to inspect(Profile, process, percent).

Transforms raw profile into a map of process identifiers to a tuple containing total count of words allocated, and a list of all traced functions sorted in the ascending order by the allocation percentage.

inspect(Profile, Type, SortBy)

(since OTP 27.0)

-spec inspect(Profile :: {trace_type(), [trace_info()]}, Type :: process | total, SortBy :: sort_by()) ->
                 #{pid() | all => profile_result()}.

Transforms raw data returned by tracing BIFs into a form convenient for subsequent analysis and formatting.

When the Type argument is process, this function returns a map of process identifiers with corresponding profiling results sorted by the selected column.

When Type argument is total or when profiling by call_count, this function returns a map with a single all key with profiling results from all processes.

The inspected profile data can be leveraged to print profiling results.

pause()

(since OTP 27.0)

-spec pause() -> ok | not_running.

Pauses trace collection for all currently traced functions, retaining existing traces.

Use continue/0 to resume trace collection.

pause(Server)

(since OTP 27.0)

-spec pause(server()) -> ok | not_running.

Equivalent to pause/0 but uses the provided Server.

profile(Fun)

(since OTP 27.0)

-spec profile(fun(() -> term())) -> ok | {term(), [trace_info()]}.

Equivalent to profile(Fun, #{}).

profile(Fun, Options)

(since OTP 27.0)

-spec profile(fun(() -> term()), profile_options()) -> ok | {term(), {trace_type(), [trace_info()]}}.

Does ad-hoc profiling of the call Fun().

By default, the result is formatted to the output device; use the report option to change this behavior.

Ad-hoc profiling starts a new instance of tprof server, runs the profiling routine, extracts results, and shuts down the server.

See profile/4 for a list of the supported options.

profile(Module, Function, Args)

(since OTP 27.0)

-spec profile(module(), Fun :: atom(), Args :: [term()]) ->
                 ok | {term(), {trace_type(), [trace_info()]}}.

Equivalent to profile(Module, Function, Args, #{}).

profile(Module, Function, Args, Options)

(since OTP 27.0)

-spec profile(module(), Fun :: atom(), Args :: [term()], profile_options()) ->
                 ok | {term(), {trace_type(), [trace_info()]}}.

Does ad-hoc profiling for the call apply(Module, Function, Args).

By default, the result is formatted to the output device; use option report to change this behavior.

Ad-hoc profiling starts a new instance of tprof server, runs the profiling routine, extracts results, and shuts down the server.

The ad-hoc profiler supports the following Options:

type - The type of profiling to perform.

device - Specifies I/O devices to print the profile to. Useful to redirect text output to console or standard_error.

pattern - Specifies a trace pattern, or a list of trace patterns to enable. By default, all functions ({'_', '_', '_'}) are traced.

report - Controls output format. The default is process; printing per-process profiling data sorted by percentage of the total allocation. Specify report => return to suppress printing and get the raw data for further evaluation with inspect/3 and formatting with format/2.

rootset - Includes extra processes in the trace list. Useful for profiling allocations for gen_server, calls, or other allocations caused by inter-process communications. See this example.

set_on_spawn - Automatically start tracing for processes spawned by the traced process. Enabled by default.

timeout - Terminate profiling after the specified amount of time (milliseconds).

restart()

(since OTP 27.0)

-spec restart() -> ok.

Clears accumulated profiles and starts profiling if it was paused.

restart(Server)

(since OTP 27.0)

-spec restart(server()) -> ok.

Equivalent to restart/0 but uses the provided Server.

set_pattern(Mod, Fun, Arity)

(since OTP 27.0)

-spec set_pattern(module(), atom(), arity() | '_') -> ok | {error, {trace_pattern, trace_pattern()}}.

Enables tracing for all functions matching the supplied pattern.

Patterns are additive, following the same rules as trace:function/4. Returns the number of functions matching the supplied pattern.

1> tprof:set_pattern(lists, seq, '_').
2
2> tprof:set_pattern(lists, keyfind, 3).
1
3> tprof:get_trace_map().
#{lists => [{keyfind,3},{seq,2},{seq,3}]}

If no functions match the pattern, an error tuple is returned:

> tprof:set_pattern(no_module, func, '_').
{error,{trace_pattern,no_module,func,'_'}}

Requires that the default tprof server has been started.

set_pattern(Server, Mod, Fun, Arity)

(since OTP 27.0)

-spec set_pattern(server(), module(), atom(), arity() | '_') ->
                     ok | {error, {trace_pattern, trace_pattern()}}.

Equivalent to set_pattern/3 but uses the provided Server.

start()

(since OTP 27.0)

-spec start() -> {ok, Server} | {error, Reason}
               when Server :: server(), Reason :: {already_started, pid()}.

Equivalent to start(#{}).

start(Config)

(since OTP 27.0)

-spec start(Config :: start_options()) -> {ok, Server} | {error, Reason}
               when Server :: server(), Reason :: {already_started, pid()}.

Starts the server, not supervised.

Profiling server stores current trace patterns and owns the trace session used for profiling.

If no session is provided in Config, then a default session called tprof is used and the profiling server is registered as tprof.

If session is provided in Config, then a session with that name is created and all profiling is done within that session. The profiling server is not registered in this case. When using tprof like this the pid/0 returned from this function needs to be provided to the functions in this module.

start_link()

(since OTP 27.0)

-spec start_link() -> {ok, Server} | {error, Reason}
                    when Server :: server(), Reason :: {already_started, pid()}.

Equivalent to start_link(#{}).

start_link(Config)

(since OTP 27.0)

-spec start_link(Config :: start_options()) -> {ok, Server} | {error, Reason}
                    when Server :: server(), Reason :: {already_started, pid()}.

Equivalent to start/1 but also links the profiling server to the caller.

stop()

(since OTP 27.0)

-spec stop() -> ok.

Stops the default tprof server and disable tracing enabled by the server.

stop(Server)

(since OTP 27.0)

-spec stop(server()) -> ok.

Equivalent to stop/0 but uses the provided Server.

xref

A Cross Reference Tool for analyzing dependencies between functions, modules, applications, and releases.

Calls between functions are either local calls such as f(), or external calls such as mod:f().

Module data, which are extracted from BEAM files, include local functions, exported functions, local calls, and external calls. By default, calls to built-in functions (BIF) are ignored, but if the option builtins, accepted by some of this module's functions, is set to true, calls to BIFs are included as well. It is the analyzing OTP version that decides what functions are BIFs. Functional objects are assumed to be called where they are created (and nowhere else).

Unresolved calls are calls to apply or spawn with variable module, variable function, or variable arguments. Examples are M:F(a), apply(M, f, [a]), and spawn(m, f(), Args). Unresolved calls are represented by calls where variable modules have been replaced with the atom '$M_EXPR', variable functions have been replaced with the atom '$F_EXPR', and variable number of arguments have been replaced with the number -1. The above mentioned examples are represented by calls to '$M_EXPR':'$F_EXPR'/1, '$M_EXPR':f/1, and m:'$F_EXPR'/-1. The unresolved calls are a subset of the external calls.

Warning

Unresolved calls make module data incomplete, which implies that the results of analyses may be invalid.

Applications are collections of modules. The BEAM files for the modules are located in the ebin subdirectory of the application directory. The name of the application directory determines the name and version of the application.

Releases are collections of applications located in the lib subdirectory of the release directory. There is more to read about applications and releases in the Design Principles book.

Xref servers are identified by names, supplied when creating new servers. Each Xref server holds a set of releases, a set of applications, and a set of modules with module data. Xref servers are independent of each other, and all analyses are evaluated in the context of one single Xref server (exceptions are the functions m/1 and d/1 which do not use servers at all).

The mode of an Xref server determines what module data are extracted from BEAM files as modules are added to the server. BEAM files compiled with the option debug_info contain "debug information", which is an abstract representation of the code.

In functions mode, which is the default mode, function calls and line numbers are extracted from debug information.

In modules mode, debug information is ignored if present, but dependencies between modules are extracted from other parts of the BEAM files. The modules mode is significantly less time and space consuming than the functions mode, but the analyses that can be done are limited.

An analyzed module is a module that has been added to an Xref server together with its module data. A library module is a module located in some directory mentioned in the library path. A library module is said to be used if some of its exported functions are used by some analyzed module. An unknown module is a module that is neither an analyzed module nor a library module, but whose exported functions are used by some analyzed module.

An unknown function is a used function that is neither local or exported by any analyzed module nor exported by any library module. An undefined function is an externally used function that is not exported by any analyzed module or library module. With this notion, a local function can be an undefined function, namely if it is externally used from some module. All unknown functions are also undefined functions; there is a figure in the User's Guide that illustrates this relationship.

The module attribute ignore_xref can be used to suppress warnings for certain modules or functions in your modules. The following forms are understood by Xref:

-ignore_xref(module).
-ignore_xref([module1, module2, module3]).

-ignore_xref(function/0).
-ignore_xref([function1/0, function2/1, function3/2]).
-ignore_xref({function,0}).
-ignore_xref([{function1,0}, {function2,1}, {function3,2}]).

%% ignoring calls/references to other modules from the current
-ignore_xref({other_mod1, func1, 0}).
-ignore_xref([{other_mod1, func1, 0}, {other_mod2, func2, 1}]).

A documented function is a function that has a corresponding -doc() attribute. These are further divided into two categories: a function whose -doc() attribute is false or hidden is documented as private, and function whose -doc() is not is documented as public.

The module attribute tag deprecated can be used to inform Xref about deprecated functions and optionally when functions are planned to be removed. A few examples show the idea:

-deprecated({f,1}). - The exported function f/1 is deprecated. Nothing is said whether f/1 will be removed or not.

-deprecated({f,1,"Use g/1 instead"}). - As above but with a descriptive string. The string is currently unused by xref but other tools can make use of it.

-deprecated({f,'_'}). - All exported functions f/0, f/1, and so on are deprecated.

-deprecated(module). - All exported functions in the module are deprecated. Equivalent to -deprecated({'_','_'})..

-deprecated([{g,1,next_version}]). - The function g/1 is deprecated and will be removed in next version.

-deprecated([{g,2,next_major_release}]). - The function g/2 is deprecated and will be removed in next major release.

-deprecated([{g,3,eventually}]). - The function g/3 is deprecated and will eventually be removed.

-deprecated({'_','_',eventually}). - All exported functions in the module are deprecated and will eventually be removed.

Likewise, the module attribute tag unsafe can be used to inform Xref about unsafe functions.

-unsafe({f,1}). - The exported function f/1 is always unsafe.

-unsafe({f,1,"Use g/1 instead"}). - As above but with a descriptive string. The string is currently unused by xref but other tools can make use of it.

-unsafe({f,1,possibly}). - The exported function f/1 is possibly unsafe

Before any analysis can take place, module data must be set up. For instance, the cross reference and the unknown functions are computed when all module data are known. The functions that need complete data (analyze/2,3, q/2,3, variables/1,2 take care of setting up data automatically. Module data need to be set up (again) after calls to any of the add, replace, remove, set_library_path/2,3, or update/1,2 functions.

The result of setting up module data is the Call Graph. A (directed) graph consists of a set of vertices and a set of (directed) edges. The edges represent calls (From, To) between functions, modules, applications, or releases. From is said to call To, and To is said to be used by From. The vertices of the Call Graph are the functions of all module data: local and exported functions of analyzed modules; used BIFs; used exported functions of library modules; and unknown functions. The functions module_info/0,1 added by the compiler are included among the exported functions, but only when called from some module. The edges are the function calls of all module data. A consequence of the edges being a set is that there is only one edge if a function is locally or externally used several times on one and the same line of code.

The Call Graph is represented by Erlang terms (the sets are lists), which is suitable for many analyses. But for analyses that look at chains of calls, a list representation is much too slow. Instead the representation offered by the digraph module is used. The translation of the list representation of the Call Graph - or a subgraph thereof - to the digraph representation does not come for free, so the language used for expressing queries to be described below has a special operator for this task and a possibility to save the digraph representation for subsequent analyses.

In addition to the Call Graph there is a graph called the Inter Call Graph. This is a graph of calls (From, To) such that there is a chain of calls from From to To in the Call Graph, and every From and To is an exported function or an unused local function. The vertices are the same as for the Call Graph.

Calls between modules, applications and releases are also directed graphs. The types of the vertices and edges of these graphs are (ranging from the most special to the most general): Fun for functions; Mod for modules; App for applications; and Rel for releases. The following paragraphs will describe the different constructs of the language used for selecting and analyzing parts of the graphs, beginning with the constants:

Expression ::= Constants

Constants ::= Consts | Consts : Type | RegExpr

Consts ::= Constant | [Constant, ...] | {Constant, ...}

Constant ::= Call | Const

Call ::= FunSpec -> FunSpec | {MFA, MFA} | AtomConst -> AtomConst | {AtomConst, AtomConst}

Const ::= AtomConst | FunSpec | MFA

AtomConst ::= Application | Module | Release

FunSpec ::= Module : Function / Arity

MFA ::= {Module, Function, Arity}

RegExpr ::= RegString : Type | RegFunc | RegFunc : Type

RegFunc ::= RegModule : RegFunction / RegArity

RegModule ::= RegAtom

RegFunction ::= RegAtom

RegArity ::= RegString | Number | _ | -1

RegAtom ::= RegString | Atom | _

RegString ::= - a regular expression, as described in the re module, enclosed in double quotes -

Type ::= Fun | Mod | App | Rel

Function ::= Atom

Application ::= Atom

Module ::= Atom

Release ::= Atom

Arity ::= Number | -1

Atom ::= - same as Erlang atoms -

Number ::= - same as non-negative Erlang integers -

Examples of constants are: kernel, kernel->stdlib, [kernel, sasl], [pg -> mnesia, {tv, mnesia}] : Mod. It is an error if an instance of Const does not match any vertex of any graph. If there are more than one vertex matching an untyped instance of AtomConst, then the one of the most general type is chosen. A list of constants is interpreted as a set of constants, all of the same type. A tuple of constants constitute a chain of calls (which may, but does not have to, correspond to an actual chain of calls of some graph). Assigning a type to a list or tuple of Constant is equivalent to assigning the type to each Constant.

Regular expressions are used as a means to select some of the vertices of a graph. A RegExpr consisting of a RegString and a type - an example is "xref_.*" : Mod - is interpreted as those modules (or applications or releases, depending on the type) that match the expression. Similarly, a RegFunc is interpreted as those vertices of the Call Graph that match the expression. An example is "xref_.*":"add_.*"/"(2|3)", which matches all add functions of arity two or three of any of the xref modules. Another example, one that matches all functions of arity 10 or more: _:_/"[1-9].+". Here _ is an abbreviation for ".*", that is, the regular expression that matches anything.

The syntax of variables is simple:

Expression ::= Variable

Variable ::= - same as Erlang variables -

There are two kinds of variables:

Predefined variables - hold module data, and cannot be assigned to but only used in queries.

User variables - can be assigned to, and are typically used for temporary results while evaluating a query, and for keeping results of queries for use in subsequent queries.

The predefined variables are (variables marked with (*) are available in functions mode only):

E - Call Graph Edges (*).

V - Call Graph Vertices (*).

M - Modules. All modules: analyzed modules, used library modules, and unknown modules.

A - Applications.

R - Releases.

ME - Module Edges. All module calls.

AE - Application Edges. All application calls.

RE - Release Edges. All release calls.

L - Local Functions (*). All local functions of analyzed modules.

X - Exported Functions. All exported functions of analyzed modules and all used exported functions of library modules.

F - Functions (*).

B - Used BIFs. B is empty if builtins is false for all analyzed modules.

U - Unknown Functions.

UU - Unused Functions (*). All local and exported functions of analyzed modules that have not been used.

XU - Externally Used Functions. Functions of all modules - including local functions - that have been used in some external call.

LU - Locally Used Functions (*). Functions of all modules that have been used in some local call.

OL - Functions with an attribute tag on_load (*).

LC - Local Calls (*).

XC - External Calls (*).

AM - Analyzed Modules.

UM - Unknown Modules.

LM - Used Library Modules.

UC - Unresolved Calls. Empty in modules mode.

EE - Inter Call Graph Edges (*).

DF - Deprecated Functions. All deprecated exported functions and all used deprecated BIFs.

DF_1 - Deprecated Functions. All deprecated functions to be removed in next version.

DF_2 - Deprecated Functions. All deprecated functions to be removed in next version or next major release.

DF_3 - Deprecated Functions. All deprecated functions to be removed in next version, next major release, or later.

DC - Documented Functions. All functions with a -doc directive.

DC_1 - Documented Public Functions. All functions whose -doc directive is not false or hidden.

DC_2 - Documented Private Functions. All functions whose -doc directive is false or hidden.

US - Unsafe Functions. All unsafe functions.

US_1 - Unsafe Functions that cannot be used safely in any way.

US_2 - Unsafe Functions that could potentially be used safely.

These are a few facts about the predefined variables (the set operators + (union) and - (difference) as well as the cast operator (Type) are described below):

F is equal to L + X.

V is equal to X + L + B + U, where X, L, B and U are pairwise disjoint (that is, have no elements in common).

UU is equal to V - (XU + LU), where LU and XU may have elements in common. Put in another way:

V is equal to UU + XU + LU.

OL is a subset of F.

E is equal to LC + XC. Note that LC and XC may have elements in common, namely if some function is locally and externally used from one and the same function.

U is a subset of XU.

B is a subset of XU.

LU is equal to range LC.

XU is equal to range XC.

LU is a subset of F.

UU is a subset of F.

range UC is a subset of U.

M is equal to AM + LM + UM, where AM, LM and UM are pairwise disjoint.

ME is equal to (Mod) E.

AE is equal to (App) E.

RE is equal to (Rel) E.

(Mod) V is a subset of M. Equality holds if all analyzed modules have some local, exported, or unknown function.

(App) M is a subset of A. Equality holds if all applications have some module.

(Rel) A is a subset of R. Equality holds if all releases have some application.

DF_1 is a subset of DF_2.

DF_2 is a subset of DF_3.

DF_3 is a subset of DF.

DF is a subset of X + B.

DC_2 is a subset of DC.

DC_1 is a subset of DC.

DC is a subset of X + B.

US_2 is a subset of US.

US_1 is a subset of US.

US is a subset of X + B.

An important notion is that of conversion of expressions. The syntax of a cast expression is:

Expression ::= ( Type ) Expression

The interpretation of the cast operator depends on the named type Type, the type of Expression, and the structure of the elements of the interpretation of Expression. If the named type is equal to the expression type, no conversion is done. Otherwise, the conversion is done one step at a time; (Fun) (App) RE, for instance, is equivalent to (Fun) (Mod) (App) RE. Now assume that the interpretation of Expression is a set of constants (functions, modules, applications or releases). If the named type is more general than the expression type, say Mod and Fun respectively, then the interpretation of the cast expression is the set of modules that have at least one of their functions mentioned in the interpretation of the expression. If the named type is more special than the expression type, say Fun and Mod, then the interpretation is the set of all the functions of the modules (in modules mode, the conversion is partial since the local functions are not known). The conversions to and from applications and releases work analogously. For instance, (App) "xref_.*" : Mod returns all applications containing at least one module such that xref_ is a prefix of the module name.

Now assume that the interpretation of Expression is a set of calls. If the named type is more general than the expression type, say Mod and Fun respectively, then the interpretation of the cast expression is the set of calls (M1, M2) such that the interpretation of the expression contains a call from some function of M1 to some function of M2. If the named type is more special than the expression type, say Fun and Mod, then the interpretation is the set of all function calls (F1, F2) such that the interpretation of the expression contains a call (M1, M2) and F1 is a function of M1 and F2 is a function of M2 (in modules mode, there are no functions calls, so a cast to Fun always yields an empty set). Again, the conversions to and from applications and releases work analogously.

The interpretation of constants and variables are sets, and those sets can be used as the basis for forming new sets by the application of set operators. The syntax:

Expression ::= Expression BinarySetOp Expression

BinarySetOp ::= + | * | -

+, * and - are interpreted as union, intersection and difference respectively: the union of two sets contains the elements of both sets; the intersection of two sets contains the elements common to both sets; and the difference of two sets contains the elements of the first set that are not members of the second set. The elements of the two sets must be of the same structure; for instance, a function call cannot be combined with a function. But if a cast operator can make the elements compatible, then the more general elements are converted to the less general element type. For instance, M + F is equivalent to (Fun) M + F, and E - AE is equivalent to E - (Fun) AE. One more example: X * xref : Mod is interpreted as the set of functions exported by the module xref; xref : Mod is converted to the more special type of X (Fun, that is) yielding all functions of xref, and the intersection with X (all functions exported by analyzed modules and library modules) is interpreted as those functions that are exported by some module and functions of xref.

There are also unary set operators:

Expression ::= UnarySetOp Expression

UnarySetOp ::= domain | range | strict

Recall that a call is a pair (From, To). domain applied to a set of calls is interpreted as the set of all vertices From, and range as the set of all vertices To. The interpretation of the strict operator is the operand with all calls of the form (A, A) removed.

The interpretation of the restriction operators is a subset of the first operand, a set of calls. The second operand, a set of vertices, is converted to the type of the first operand. The syntax of the restriction operators:

Expression ::= Expression RestrOp Expression

RestrOp ::= |

RestrOp ::= ||

RestrOp ::= |||

The interpretation in some detail for the three operators:

| - The subset of calls from any of the vertices.

|| - The subset of calls to any of the vertices.

||| - The subset of calls to and from any of the vertices. For all sets of calls CS and all sets of vertices VS, CS ||| VS is equivalent to CS | VS * CS || VS.

Two functions (modules, applications, releases) belong to the same strongly connected component if they call each other (in)directly. The interpretation of the components operator is the set of strongly connected components of a set of calls. The condensation of a set of calls is a new set of calls between the strongly connected components such that there is an edge between two components if there is some constant of the first component that calls some constant of the second component.

The interpretation of the of operator is a chain of calls of the second operand (a set of calls) that passes throw all of the vertices of the first operand (a tuple of constants), in the given order. The second operand is converted to the type of the first operand. For instance, the of operator can be used for finding out whether a function calls another function indirectly, and the chain of calls demonstrates how. The syntax of the graph analyzing operators:

Expression ::= Expression BinaryGraphOp Expression

Expression ::= UnaryGraphOp Expression

UnaryGraphOp ::= components | condensation

BinaryGraphOp ::= of

As was mentioned before, the graph analyses operate on the digraph representation of graphs. By default, the digraph representation is created when needed (and deleted when no longer used), but it can also be created explicitly by use of the closure operator:

Expression ::= ClosureOp Expression

ClosureOp ::= closure

The interpretation of the closure operator is the transitive closure of the operand.

The restriction operators are defined for closures as well; closure E | xref : Mod is interpreted as the direct or indirect function calls from the xref module, while the interpretation of E | xref : Mod is the set of direct calls from xref. If some graph is to be used in several graph analyses, it saves time to assign the digraph representation of the graph to a user variable, and then make sure that every graph analysis operates on that variable instead of the list representation of the graph.

The lines where functions are defined (more precisely: where the first clause begins) and the lines where functions are used are available in functions mode. The line numbers refer to the files where the functions are defined. This holds also for files included with the -include and -include_lib directives, which may result in functions defined apparently in the same line. The line operators are used for assigning line numbers to functions and for assigning sets of line numbers to function calls. The syntax is similar to the one of the cast operator:

Expression ::= ( LineOp) Expression

Expression ::= ( XLineOp) Expression

LineOp ::= Lin | ELin | LLin | XLin

XLineOp ::= XXL

The interpretation of the Lin operator applied to a set of functions assigns to each function the line number where the function is defined. Unknown functions and functions of library modules are assigned the number 0.

The interpretation of some LineOp operator applied to a set of function calls assigns to each call the set of line numbers where the first function calls the second function. Not all calls are assigned line numbers by all operators:

the Lin operator is defined for Call Graph Edges;

the LLin operator is defined for Local Calls.

the XLin operator is defined for External Calls.

the ELin operator is defined for Inter Call Graph Edges.

The Lin (LLin, XLin) operator assigns the lines where calls (local calls, external calls) are made. The ELin operator assigns to each call (From, To), for which it is defined, every line L such that there is a chain of calls from From to To beginning with a call on line L.

The XXL operator is defined for the interpretation of any of the LineOp operators applied to a set of function calls. The result is that of replacing the function call with a line numbered function call, that is, each of the two functions of the call is replaced by a pair of the function and the line where the function is defined. The effect of the XXL operator can be undone by the LineOp operators. For instance, (Lin) (XXL) (Lin) E is equivalent to (Lin) E.

The +, -, *, and # operators are defined for line number expressions, provided the operands are compatible. The LineOp operators are also defined for modules, applications, and releases; the operand is implicitly converted to functions. Similarly, the cast operator is defined for the interpretation of the LineOp operators.

The interpretation of the counting operator is the number of elements of a set. The operator is undefined for closures. The +, - and * operators are interpreted as the obvious arithmetical operators when applied to numbers. The syntax of the counting operator:

Expression ::= CountOp Expression

CountOp ::= #

All binary operators are left associative; for instance, A | B  || C is equivalent to (A | B) || C. The following is a list of all operators, in increasing order of precedence:

+, -

*

#

|, ||, |||

of

(Type)

closure, components, condensation, domain, range, strict

Parentheses are used for grouping, either to make an expression more readable or to override the default precedence of operators:

Expression ::= ( Expression )

A query is a non-empty sequence of statements. A statement is either an assignment of a user variable or an expression. The value of an assignment is the value of the right hand side expression. It makes no sense to put a plain expression anywhere else but last in queries. The syntax of queries is summarized by these productions:

Query ::= Statement, ...

Statement ::= Assignment | Expression

Assignment ::= Variable := Expression | Variable = Expression

A variable cannot be assigned a new value unless first removed. Variables assigned to by the = operator are removed at the end of the query, while variables assigned to by the := operator can only be removed by calls to forget. There are no user variables when module data need to be set up again; if any of the functions that make it necessary to set up module data again is called, all user variables are forgotten.

See Also

beam_lib, digraph, digraph_utils, re, User's Guide for Xref

Summary

Types

add_dir_rsn()

add_mod_rsn()

analysis()

analyze_rsn()

answer()

app_spec()

application()

call()

component()

constant()

define_at()

depr_flag()

directory()

file()

file_error()

func_spec()

funcall()

function_name()

info()

library()

library_path()

mod_spec()

mode()

path()

q_rsn()

rel_spec()

release()

string_position()

variable()

xarity()

xmfa()

xref()

Functions

add_application(XrefServer, Directory)

Equivalent to add_application(XrefServer, Directory, []).

add_application(XrefServer, Directory, Options)

Adds an application, the modules of the application, and module data of the modules to an Xref server.

add_directory(XrefServer, Directory)

Equivalent to add_directory(Name, Directory, []).

add_directory(XrefServer, Directory, Options)

Adds the modules found in the given directory and the modules' data to an Xref server.

add_module(XrefServer, File)

Equivalent to add_module(Name, File, []).

add_module(XrefServer, File, Options)

Adds a module and its module data to an Xref server.

add_release(XrefServer, Directory)

Equivalent to add_release(Name, Directory, []).

add_release(XrefServer, Directory, Options)

Adds a release, the applications of the release, the modules of the applications, and module data of the modules to an Xref server.

analyze(XrefServer, Analysis)

Equivalent to analyze(XrefServer, Analysis, []).

analyze(XrefServer, Analysis, Options)

Evaluates a predefined analysis.

d(Directory)

The modules found in the given directory are checked for calls to deprecated functions, calls to undefined functions, and for unused local functions.

forget(XrefServer)

Removes all user variables of an Xref server.

forget(XrefServer, Variables)

Removes the user variables given by Variables from an Xref server.

format_error(Error)

Given the error returned by any function of this module, the function format_error returns a descriptive string of the error in English.

get_default(XrefServer)

Returns a list of all options and their default values.

get_default(XrefServer, Option)

Returns the default value for option Option.

get_library_path(XrefServer)

Returns the library path.

info(XrefServer)

The info/1 function returns information as a list of pairs {Tag, term() in some order about the state and the module data of an Xref server.

info(XrefServer, Category)

Returns information about all items belonging to category Category. See info/3 for details.

info(XrefServer, Category, Items)

The info functions return information as a list of pairs {Tag, term()} in some order about the state and the module data of an Xref server.

m(FileOrModule)

The given BEAM file (with or without the .beam extension) or the file found by calling code:which(Module) is checked for calls to deprecated functions, calls to undefined functions, and for unused local functions.

q(XrefServer, Query)

Equivalent to q(XrefServer, Query, []).

q(XrefServer, Query, Options)

Evaluates a query in the context of an Xref server, and returns the value of the last statement.

remove_application(XrefServer, Applications)

Removes applications and their modules and module data from an Xref server.

remove_module(XrefServer, Modules)

Removes analyzed modules and module data from an Xref server.

remove_release(XrefServer, Releases)

Removes releases and their applications, modules, and module data from an Xref server.

replace_application(XrefServer, Application, Directory)

Equivalent to replace_application(XrefServer, Application, Directory, []).

replace_application(XrefServer, Application, Directory, Options)

Replaces the modules of an application with other modules read from an application directory.

replace_module(XrefServer, Module, File)

Equivalent to replace_module(XrefServer, Module, File, []).

replace_module(XrefServer, Module, File, Options)

Replaces module data of an analyzed module with data read from a BEAM file.

set_default(XrefServer, OptionValues)

Sets default values for multiple options given by OptionValues.

set_default(XrefServer, Option, Value)

Sets the default value of one or more options.

set_library_path(XrefServer, LibraryPath)

Equivalent to set_library_path(XrefServer, LibraryPath, []).

set_library_path(XrefServer, LibraryPath, Options)

Sets the library path.

start(NameOrOptions)

Creates an Xref server.

start(Name, Options)

Creates an Xref server with a given name.

stop(XrefServer)

Stops an Xref server.

update(XrefServer)

Equivalent to update(XrefServer, []).

update(XrefServer, Options)

Replaces the module data of all analyzed modules the BEAM files of which have been modified since last read by an add function or update.

variables(XrefServer)

Equivalent to variables(XrefServer, []).

variables(XrefServer, Options)

Returns a sorted lists of the names of the variables of an Xref server.

Types

add_dir_rsn()

(not exported)

-type add_dir_rsn() ::
          {file_error, file(), file_error()} |
          {invalid_filename, term()} |
          {invalid_options, term()} |
          {unrecognized_file, file()} |
          beam_lib:chnk_rsn().

add_mod_rsn()

(not exported)

-type add_mod_rsn() ::
          {file_error, file(), file_error()} |
          {invalid_filename, term()} |
          {invalid_options, term()} |
          {module_clash, {module(), file(), file()}} |
          {no_debug_info, file()} |
          beam_lib:chnk_rsn().

analysis()

(not exported)

-type analysis() ::
          undefined_function_calls | undefined_functions | locals_not_used | exports_not_used |
          deprecated_function_calls |
          {deprecated_function_calls, DeprFlag :: depr_flag()} |
          deprecated_functions |
          {deprecated_functions, DeprFlag :: depr_flag()} |
          private_function_calls | undocumented_function_calls | unsafe_function_calls |
          {call, FuncSpec :: func_spec()} |
          {use, FuncSpec :: func_spec()} |
          {module_call, ModSpec :: mod_spec()} |
          {module_use, ModSpec :: mod_spec()} |
          {application_call, AppSpec :: app_spec()} |
          {application_use, AppSpec :: app_spec()} |
          {release_call, RelSpec :: rel_spec()} |
          {release_use, RelSpec :: rel_spec()}.

analyze_rsn()

(not exported)

-type analyze_rsn() ::
          {invalid_options, term()} |
          {parse_error, string_position(), term()} |
          {unavailable_analysis, term()} |
          {unknown_analysis, term()} |
          {unknown_constant, string()} |
          {unknown_variable, variable()}.

answer()

(not exported)

-type answer() ::
          false |
          [constant()] |
          [(Call :: call()) | (ComponentCall :: {component(), component()})] |
          [Component :: component()] |
          non_neg_integer() |
          [DefineAt :: define_at()] |
          [CallAt :: {funcall(), LineNumbers :: [non_neg_integer()]}] |
          [AllLines :: {{define_at(), define_at()}, LineNumbers :: [non_neg_integer()]}].

app_spec()

(not exported)

-type app_spec() :: application() | [application()].

application()

(not exported)

-type application() :: atom().

call()

(not exported)

-type call() :: {atom(), atom()} | funcall().

component()

(not exported)

-type component() :: [constant()].

constant()

(not exported)

-type constant() :: xmfa() | module() | application() | release().

define_at()

(not exported)

-type define_at() :: {xmfa(), LineNumber :: non_neg_integer()}.

depr_flag()

(not exported)

-type depr_flag() :: next_version | next_major_release | eventually.

directory()

(not exported)

-type directory() :: atom() | file:filename().

file()

(not exported)

-type file() :: file:filename().

file_error()

(not exported)

-type file_error() :: atom().

func_spec()

(not exported)

-type func_spec() :: xmfa() | [xmfa()].

funcall()

(not exported)

-type funcall() :: {xmfa(), xmfa()}.

function_name()

(not exported)

-type function_name() :: atom().

info()

(not exported)

-type info() ::
          {application, Application :: [application()]} |
          {builtins, boolean()} |
          {directory, directory()} |
          {library_path, library_path()} |
          {mode, mode()} |
          {no_analyzed_modules, non_neg_integer()} |
          {no_applications, non_neg_integer()} |
          {no_calls, {NoResolved :: non_neg_integer(), NoUnresolved :: non_neg_integer()}} |
          {no_function_calls,
           {NoLocal :: non_neg_integer(),
            NoResolvedExternal :: non_neg_integer(),
            NoUnresolved :: non_neg_integer()}} |
          {no_functions, {NoLocal :: non_neg_integer(), NoExternal :: non_neg_integer()}} |
          {no_inter_function_calls, non_neg_integer()} |
          {no_releases, non_neg_integer()} |
          {release, Release :: [release()]} |
          {version, Version :: [non_neg_integer()]}.

library()

(not exported)

-type library() :: atom().

library_path()

(not exported)

-type library_path() :: path() | code_path.

mod_spec()

(not exported)

-type mod_spec() :: module() | [module()].

mode()

(not exported)

-type mode() :: functions | modules.

path()

(not exported)

-type path() :: [file()].

q_rsn()

(not exported)

-type q_rsn() ::
          {invalid_options, term()} |
          {parse_error, string_position(), term()} |
          {type_error, string()} |
          {type_mismatch, string(), string()} |
          {unknown_analysis, term()} |
          {unknown_constant, string()} |
          {unknown_variable, variable()} |
          {variable_reassigned, string()}.

rel_spec()

(not exported)

-type rel_spec() :: release() | [release()].

release()

(not exported)

-type release() :: atom().

string_position()

(not exported)

-type string_position() :: pos_integer().

variable()

(not exported)

-type variable() :: atom().

xarity()

(not exported)

-type xarity() :: arity() | -1.

xmfa()

(not exported)

-type xmfa() :: {module(), function_name(), xarity()}.

xref()

(not exported)

-type xref() :: atom() | pid().

Functions

add_application(XrefServer, Directory)

-spec add_application(XrefServer, Directory) -> {ok, application()} | {error, module(), Reason}
                         when
                             XrefServer :: xref(),
                             Directory :: directory(),
                             Reason ::
                                 {application_clash, {application(), directory(), directory()}} |
                                 add_dir_rsn().

Equivalent to add_application(XrefServer, Directory, []).

add_application(XrefServer, Directory, Options)

-spec add_application(XrefServer, Directory, Options) -> {ok, application()} | {error, module(), Reason}
                         when
                             XrefServer :: xref(),
                             Directory :: directory(),
                             Options :: Option | [Option],
                             Option ::
                                 {builtins, boolean()} |
                                 {name, application()} |
                                 {verbose, boolean()} |
                                 {warnings, boolean()} |
                                 builtins | verbose | warnings,
                             Reason ::
                                 {application_clash, {application(), directory(), directory()}} |
                                 add_dir_rsn().

Adds an application, the modules of the application, and module data of the modules to an Xref server.

The modules will be members of the application. The default is to use the base name of the directory with the version removed as application name, but this can be overridden by the name option. Returns the name of the application.

If the given directory has a subdirectory named ebin, modules (BEAM files) are searched for in that directory, otherwise modules are searched for in the given directory.

If the mode of the Xref server is functions, BEAM files that contain no debug information are ignored.

add_directory(XrefServer, Directory)

-spec add_directory(XrefServer, Directory) -> {ok, Modules} | {error, module(), Reason}
                       when
                           XrefServer :: xref(),
                           Directory :: directory(),
                           Modules :: [module()],
                           Reason ::
                               {application_clash, {application(), directory(), directory()}} |
                               add_dir_rsn().

Equivalent to add_directory(Name, Directory, []).

add_directory(XrefServer, Directory, Options)

-spec add_directory(XrefServer, Directory, Options) -> {ok, Modules} | {error, module(), Reason}
                       when
                           XrefServer :: xref(),
                           Directory :: directory(),
                           Options :: Option | [Option],
                           Option ::
                               {builtins, boolean()} |
                               {recurse, boolean()} |
                               {verbose, boolean()} |
                               {warnings, boolean()} |
                               builtins | recurse | verbose | warnings,
                           Modules :: [module()],
                           Reason :: add_dir_rsn().

Adds the modules found in the given directory and the modules' data to an Xref server.

The default is not to examine subdirectories, but if the option recurse has the value true, modules are searched for in subdirectories on all levels as well as in the given directory. Returns a sorted list of the names of the added modules.

The modules added will not be members of any applications.

If the mode of the Xref server is functions, BEAM files that contain no debug information are ignored.

add_module(XrefServer, File)

-spec add_module(XrefServer, File) -> {ok, module()} | {error, module(), Reason}
                    when XrefServer :: xref(), File :: file:filename(), Reason :: add_mod_rsn().

Equivalent to add_module(Name, File, []).

add_module(XrefServer, File, Options)

-spec add_module(XrefServer, File, Options) -> {ok, module()} | {error, module(), Reason}
                    when
                        XrefServer :: xref(),
                        File :: file:filename(),
                        Options :: Option | [Option],
                        Option ::
                            {builtins, boolean()} |
                            {verbose, boolean()} |
                            {warnings, boolean()} |
                            builtins | verbose | warnings,
                        Reason :: add_mod_rsn().

Adds a module and its module data to an Xref server.

The module will not be member of any application. Returns the name of the module.

If the mode of the Xref server is functions, and the BEAM file contains no debug information, the error message no_debug_info is returned.

add_release(XrefServer, Directory)

-spec add_release(XrefServer, Directory) -> {ok, release()} | {error, module(), Reason}
                     when
                         XrefServer :: xref(),
                         Directory :: directory(),
                         Reason ::
                             {application_clash, {application(), directory(), directory()}} |
                             {release_clash, {release(), directory(), directory()}} |
                             add_dir_rsn().

Equivalent to add_release(Name, Directory, []).

add_release(XrefServer, Directory, Options)

-spec add_release(XrefServer, Directory, Options) -> {ok, release()} | {error, module(), Reason}
                     when
                         XrefServer :: xref(),
                         Directory :: directory(),
                         Options :: Option | [Option],
                         Option ::
                             {builtins, boolean()} |
                             {name, release()} |
                             {verbose, boolean()} |
                             {warnings, boolean()} |
                             builtins | verbose | warnings,
                         Reason ::
                             {application_clash, {application(), directory(), directory()}} |
                             {release_clash, {release(), directory(), directory()}} |
                             add_dir_rsn().

Adds a release, the applications of the release, the modules of the applications, and module data of the modules to an Xref server.

The applications will be members of the release, and the modules will be members of the applications. The default is to use the base name of the directory as release name, but this can be overridden by the name option. Returns the name of the release.

If the given directory has a subdirectory named lib, the directories in that directory are assumed to be application directories, otherwise all subdirectories of the given directory are assumed to be application directories. If there are several versions of some application, the one with the highest version is chosen.

If the mode of the Xref server is functions, BEAM files that contain no debug information are ignored.

analyze(XrefServer, Analysis)

-spec analyze(XrefServer, Analysis) -> {ok, Answer} | {error, module(), Reason}
                 when
                     XrefServer :: xref(),
                     Analysis :: analysis(),
                     Answer :: [term()],
                     Reason :: analyze_rsn().

Equivalent to analyze(XrefServer, Analysis, []).

analyze(XrefServer, Analysis, Options)

-spec analyze(XrefServer, Analysis, Options) -> {ok, Answer} | {error, module(), Reason}
                 when
                     XrefServer :: xref(),
                     Analysis :: analysis(),
                     Options :: Option | [Option],
                     Option :: {verbose, boolean()} | verbose,
                     Answer :: [term()],
                     Reason :: analyze_rsn().

Evaluates a predefined analysis.

Returns a sorted list without duplicates of call/0 or constant/0, depending on the chosen analysis. The predefined analyses, which operate on all analyzed modules, are (analyses marked with (*) are available only in mode functions):

private_function_calls - Returns a list of calls to private functions from applications other than the one the callee is defined in.

undocumented_function_calls - Returns a list of calls to functions lacking a -doc() directive from applications other than the one the callee is defined in.

unsafe_function_calls - Returns a list of unsafe functions. Note that this implies private_function_calls.

undefined_function_calls(*) - Returns a list of calls to undefined functions.

undefined_functions - Returns a list of undefined functions.

locals_not_used(*) - Returns a list of local functions that have not been locally used.

exports_not_used - Returns a list of exported functions that have not been externally used. Note that in modules mode, M:behaviour_info/1 is never reported as unused.

deprecated_function_calls(*) - Returns a list of external calls to deprecated functions.

{deprecated_function_calls, DeprFlag}(*) - Returns a list of external calls to deprecated functions. If DeprFlag is equal to next_version, calls to functions to be removed in next version are returned. If DeprFlag is equal to next_major_release, calls to functions to be removed in next major release are returned as well as calls to functions to be removed in next version. Finally, if DeprFlag is equal to eventually, all calls to functions to be removed are returned, including calls to functions to be removed in next version or next major release.

deprecated_functions - Returns a list of externally used deprecated functions.

{deprecated_functions, DeprFlag} - Returns a list of externally used deprecated functions. If DeprFlag is equal to next_version, functions to be removed in next version are returned. If DeprFlag is equal to next_major_release, functions to be removed in next major release are returned as well as functions to be removed in next version. Finally, if DeprFlag is equal to eventually, all functions to be removed are returned, including functions to be removed in next version or next major release.

{call, FuncSpec}(*) - Returns a list of functions called by some of the given functions.

{use, FuncSpec}(*) - Returns a list of functions that use some of the given functions.

{module_call, ModSpec} - Returns a list of modules called by some of the given modules.

{module_use, ModSpec} - Returns a list of modules that use some of the given modules.

{application_call, AppSpec} - Returns a list of applications called by some of the given applications.

{application_use, AppSpec} - Returns a list of applications that use some of the given applications.

{release_call, RelSpec} - Returns a list of releases called by some of the given releases.

{release_use, RelSpec} - Returns a list of releases that use some of the given releases.

d(Directory)

-spec d(Directory) -> [DebugInfoResult] | [NoDebugInfoResult] | {error, module(), Reason}
           when
               Directory :: directory(),
               DebugInfoResult ::
                   {deprecated, [funcall()]} | {undefined, [funcall()]} | {unused, [mfa()]},
               NoDebugInfoResult :: {deprecated, [xmfa()]} | {undefined, [xmfa()]},
               Reason ::
                   {file_error, file(), file_error()} |
                   {invalid_filename, term()} |
                   {unrecognized_file, file()} |
                   beam_lib:chnk_rsn().

The modules found in the given directory are checked for calls to deprecated functions, calls to undefined functions, and for unused local functions.

The code path is used as library path.

If some of the found BEAM files contain debug information, then those modules are checked and a list of tuples is returned. The first element of each tuple is one of:

deprecated, the second element is a sorted list of calls to deprecated functions;

undefined, the second element is a sorted list of calls to undefined functions;

unused, the second element is a sorted list of unused local functions.

If no BEAM file contains debug information, then a list of tuples is returned. The first element of each tuple is one of:

deprecated, the second element is a sorted list of externally used deprecated functions;

undefined, the second element is a sorted list of undefined functions.

forget(XrefServer)

-spec forget(XrefServer) -> ok when XrefServer :: xref().

Removes all user variables of an Xref server.

forget(XrefServer, Variables)

-spec forget(XrefServer, Variables) -> ok | {error, module(), Reason}
                when
                    XrefServer :: xref(),
                    Variables :: variable() | [variable()],
                    Reason :: {not_user_variable, term()}.

Removes the user variables given by Variables from an Xref server.

format_error(Error)

-spec format_error(Error) -> io_lib:chars() when Error :: {error, module(), Reason :: term()}.

Given the error returned by any function of this module, the function format_error returns a descriptive string of the error in English.

For file errors, the function file:format_error/1 is called.

get_default(XrefServer)

-spec get_default(XrefServer) -> [{Option, Value}]
                     when
                         XrefServer :: xref(),
                         Option :: builtins | recurse | verbose | warnings,
                         Value :: boolean().

Returns a list of all options and their default values.

get_default(XrefServer, Option)

-spec get_default(XrefServer, Option) -> {ok, Value} | {error, module(), Reason}
                     when
                         XrefServer :: xref(),
                         Option :: builtins | recurse | verbose | warnings,
                         Value :: boolean(),
                         Reason :: {invalid_options, term()}.

Returns the default value for option Option.

get_library_path(XrefServer)

-spec get_library_path(XrefServer) -> {ok, LibraryPath}
                          when XrefServer :: xref(), LibraryPath :: library_path().

Returns the library path.

info(XrefServer)

-spec info(XrefServer) -> [Info] when XrefServer :: xref(), Info :: info().

The info/1 function returns information as a list of pairs {Tag, term() in some order about the state and the module data of an Xref server.

info/1 returns information with the following tags (tags marked with (*) are only available in functions mode):

library_path, the library path;

mode, the mode;

no_releases, number of releases;

no_applications, total number of applications (of all releases);

no_analyzed_modules, total number of analyzed modules;

no_calls (*), total number of calls (in all modules), regarding instances of one function call in different lines as separate calls;

no_function_calls (*), total number of local calls, resolved external calls and unresolved calls;

no_functions (*), total number of local and exported functions;

no_inter_function_calls (*), total number of calls of the Inter Call Graph.

info(XrefServer, Category)

-spec info(XrefServer, Category) -> [{Item, [Info]}] | {error, module(), {no_such_info, Category}}
              when
                  XrefServer :: xref(),
                  Category :: modules | applications | releases | libraries,
                  Item :: module() | application() | release() | library(),
                  Info :: info().

Returns information about all items belonging to category Category. See info/3 for details.

info(XrefServer, Category, Items)

-spec info(XrefServer, Category, Items) -> [{Item, [Info]}] | {error, module(), Reason}
              when
                  XrefServer :: xref(),
                  Category :: modules | applications | releases | libraries,
                  Items :: Item | [Item],
                  Item :: module() | application() | release() | library(),
                  Info :: info(),
                  Reason ::
                      {no_such_application, Item} |
                      {no_such_info, Category} |
                      {no_such_library, Item} |
                      {no_such_module, Item} |
                      {no_such_release, Item}.

The info functions return information as a list of pairs {Tag, term()} in some order about the state and the module data of an Xref server.

info/2 and info/3 return information about all or some of the analyzed modules, applications, releases, or library modules of an Xref server. The following information is returned for every analyzed module:

application, an empty list if the module does not belong to any application, otherwise a list of the application name;

builtins, whether calls to BIFs are included in the module's data;

directory, the directory where the module's BEAM file is located;

no_calls (*), number of calls, regarding instances of one function call in different lines as separate calls;

no_function_calls (*), number of local calls, resolved external calls and unresolved calls;

no_functions (*), number of local and exported functions;

no_inter_function_calls (*), number of calls of the Inter Call Graph;

The following information is returned for every application:

directory, the directory where the modules' BEAM files are located;

no_analyzed_modules, number of analyzed modules;

no_calls (*), number of calls of the application's modules, regarding instances of one function call in different lines as separate calls;

no_function_calls (*), number of local calls, resolved external calls and unresolved calls of the application's modules;

no_functions (*), number of local and exported functions of the application's modules;

no_inter_function_calls (*), number of calls of the Inter Call Graph of the application's modules;

release, an empty list if the application does not belong to any release, otherwise a list of the release name;

version, the application's version as a list of numbers. For instance, the directory "kernel-2.6" results in the application name kernel and the application version [2,6]; "kernel" yields the name kernel and the version [].

The following information is returned for every release:

directory, the release directory;

no_analyzed_modules, number of analyzed modules;

no_applications, number of applications;

no_calls (*), number of calls of the release's modules, regarding instances of one function call in different lines as separate calls;

no_function_calls (*), number of local calls, resolved external calls and unresolved calls of the release's modules;

no_functions (*), number of local and exported functions of the release's modules;

no_inter_function_calls (*), number of calls of the Inter Call Graph of the release's modules.

The following information is returned for every library module:

directory, the directory where the library module's BEAM file is located.

For every number of calls, functions, and so on returned by the no_ tags, there is a query returning the same number. Listed below are examples of such queries. Some of the queries return the sum of a two or more of the no_ tags numbers. mod (app, rel) refers to any module (application, release).

no_analyzed_modules

"# AM" (info/1)

"# (Mod) app:App" (application)

"# (Mod) rel:Rel" (release)

no_applications

"# A" (info/1)

no_calls. The sum of the number of resolved and unresolved calls:

"# (XLin) E + # (LLin) E" (info/1)

"T = E | mod:Mod, # (LLin) T + # (XLin) T" (module)

"T = E | app:App, # (LLin) T + # (XLin) T" (application)

"T = E | rel:Rel, # (LLin) T + # (XLin) T" (release)

no_functions. Functions in library modules and the functions module_info/0,1 are not counted by info. Assuming that "Extra := _:module_info/\"(0|1)\" + LM" has been evaluated, the sum of the number of local and exported functions are:

"# (F - Extra)" (info/1)

"# (F * mod:Mod - Extra)" (module)

"# (F * app:App - Extra)" (application)

"# (F * rel:Rel - Extra)" (release)

no_function_calls. The sum of the number of local calls, resolved external calls and unresolved calls:

"# LC + # XC" (info/1)

"# LC | mod:Mod + # XC | mod:Mod" (module)

"# LC | app:App + # XC | app:App" (application)

"# LC | rel:Rel + # XC | mod:Rel" (release)

no_inter_function_calls

"# EE" (info/1)

"# EE | mod:Mod" (module)

"# EE | app:App" (application)

"# EE | rel:Rel" (release)

no_releases

"# R" (info/1)

m(FileOrModule)

-spec m(FileOrModule) -> [DebugInfoResult] | [NoDebugInfoResult] | {error, module(), Reason}
           when
               FileOrModule :: file:filename() | module(),
               DebugInfoResult ::
                   {deprecated, [funcall()]} | {undefined, [funcall()]} | {unused, [mfa()]},
               NoDebugInfoResult :: {deprecated, [xmfa()]} | {undefined, [xmfa()]},
               Reason ::
                   {cover_compiled, Module :: module()} |
                   {file_error, file(), file_error()} |
                   {interpreted, Module :: module()} |
                   {invalid_filename, term()} |
                   {no_such_module, Module :: module()} |
                   beam_lib:chnk_rsn().

The given BEAM file (with or without the .beam extension) or the file found by calling code:which(Module) is checked for calls to deprecated functions, calls to undefined functions, and for unused local functions.

The code path is used as library path.

If the BEAM file contains debug information, a list of tuples is returned. The first element of each tuple is one of:

deprecated, the second element is a sorted list of calls to deprecated functions;

undefined, the second element is a sorted list of calls to undefined functions;

unused, the second element is a sorted list of unused local functions.

If the BEAM file does not contain debug information, a list of tuples is returned. The first element of each tuple is one of:

deprecated, the second element is a sorted list of externally used deprecated functions;

undefined, the second element is a sorted list of undefined functions.

q(XrefServer, Query)

-spec q(XrefServer, Query) -> {ok, Answer} | {error, module(), Reason}
           when XrefServer :: xref(), Query :: string() | atom(), Answer :: answer(), Reason :: q_rsn().

Equivalent to q(XrefServer, Query, []).

q(XrefServer, Query, Options)

-spec q(XrefServer, Query, Options) -> {ok, Answer} | {error, module(), Reason}
           when
               XrefServer :: xref(),
               Query :: string() | atom(),
               Options :: Option | [Option],
               Option :: {verbose, boolean()} | verbose,
               Answer :: answer(),
               Reason :: q_rsn().

Evaluates a query in the context of an Xref server, and returns the value of the last statement.

The syntax of the value depends on the expression:

A set of calls is represented by a sorted list without duplicates of call/0.

A set of constants is represented by a sorted list without duplicates of constant/0.

A set of strongly connected components is a sorted list without duplicates of Component.

A set of calls between strongly connected components is a sorted list without duplicates of ComponentCall.

A chain of calls is represented by a list of constant/0. The list contains the From vertex of every call and the To vertex of the last call.

The of operator returns false if no chain of calls between the given constants can be found.

The value of the closure operator (the digraph representation) is represented by the atom 'closure()'.

A set of line numbered functions is represented by a sorted list without duplicates of DefineAt.

A set of line numbered function calls is represented by a sorted list without duplicates of CallAt.

A set of line numbered functions and function calls is represented by a sorted list without duplicates of AllLines.

For both CallAt and AllLines it holds that for no list element is LineNumbers an empty list; such elements have been removed. The constants of component and the integers of LineNumbers are sorted and without duplicates.

remove_application(XrefServer, Applications)

-spec remove_application(XrefServer, Applications) -> ok | {error, module(), Reason}
                            when
                                XrefServer :: xref(),
                                Applications :: application() | [application()],
                                Reason :: {no_such_application, application()}.

Removes applications and their modules and module data from an Xref server.

remove_module(XrefServer, Modules)

-spec remove_module(XrefServer, Modules) -> ok | {error, module(), Reason}
                       when
                           XrefServer :: xref(),
                           Modules :: module() | [module()],
                           Reason :: {no_such_module, module()}.

Removes analyzed modules and module data from an Xref server.

remove_release(XrefServer, Releases)

-spec remove_release(XrefServer, Releases) -> ok | {error, module(), Reason}
                        when
                            XrefServer :: xref(),
                            Releases :: release() | [release()],
                            Reason :: {no_such_release, release()}.

Removes releases and their applications, modules, and module data from an Xref server.

replace_application(XrefServer, Application, Directory)

-spec replace_application(XrefServer, Application, Directory) ->
                             {ok, Application} | {error, module(), Reason}
                             when
                                 XrefServer :: xref(),
                                 Application :: application(),
                                 Directory :: directory(),
                                 Reason :: {no_such_application, Application} | add_dir_rsn().

Equivalent to replace_application(XrefServer, Application, Directory, []).

replace_application(XrefServer, Application, Directory, Options)

-spec replace_application(XrefServer, Application, Directory, Options) ->
                             {ok, Application} | {error, module(), Reason}
                             when
                                 XrefServer :: xref(),
                                 Application :: application(),
                                 Directory :: directory(),
                                 Options :: Option | [Option],
                                 Option ::
                                     {builtins, boolean()} |
                                     {verbose, boolean()} |
                                     {warnings, boolean()} |
                                     builtins | verbose | warnings,
                                 Reason ::
                                     {application_clash, {application(), directory(), directory()}} |
                                     {no_such_application, Application} |
                                     add_dir_rsn().

Replaces the modules of an application with other modules read from an application directory.

Release membership of the application is retained. Note that the name of the application is kept; the name of the given directory is not used.

replace_module(XrefServer, Module, File)

-spec replace_module(XrefServer, Module, File) -> {ok, Module} | {error, module(), Reason}
                        when
                            XrefServer :: xref(),
                            Module :: module(),
                            File :: file(),
                            Reason ::
                                {module_mismatch, Module, ReadModule :: module()} |
                                {no_such_module, Module} |
                                add_mod_rsn().

Equivalent to replace_module(XrefServer, Module, File, []).

replace_module(XrefServer, Module, File, Options)

-spec replace_module(XrefServer, Module, File, Options) -> {ok, Module} | {error, module(), Reason}
                        when
                            XrefServer :: xref(),
                            Module :: module(),
                            File :: file(),
                            Options :: Option | [Option],
                            Option :: {verbose, boolean()} | {warnings, boolean()} | verbose | warnings,
                            Reason ::
                                {module_mismatch, Module, ReadModule :: module()} |
                                {no_such_module, Module} |
                                add_mod_rsn().

Replaces module data of an analyzed module with data read from a BEAM file.

Application membership of the module is retained, and so is the value of the builtins option of the module. An error is returned if the name of the read module differs from the given module.

The update function is an alternative for updating module data of recompiled modules.

set_default(XrefServer, OptionValues)

-spec set_default(XrefServer, OptionValues) -> ok | {error, module(), Reason}
                     when
                         XrefServer :: xref(),
                         OptionValues :: OptionValue | [OptionValue],
                         OptionValue :: {Option, Value},
                         Option :: builtins | recurse | verbose | warnings,
                         Value :: boolean(),
                         Reason :: {invalid_options, term()}.

Sets default values for multiple options given by OptionValues.

See set_default/3 for the name of options and their allowed values.

set_default(XrefServer, Option, Value)

-spec set_default(XrefServer, Option, Value) -> {ok, OldValue} | {error, module(), Reason}
                     when
                         XrefServer :: xref(),
                         Option :: builtins | recurse | verbose | warnings,
                         Value :: boolean(),
                         OldValue :: boolean(),
                         Reason :: {invalid_options, term()}.

Sets the default value of one or more options.

The options that can be set this way are:

builtins, with initial default value false;

recurse, with initial default value false;

verbose, with initial default value false;

warnings, with initial default value true.

The initial default values are set when creating an Xref server.

set_library_path(XrefServer, LibraryPath)

-spec set_library_path(XrefServer, LibraryPath) -> ok | {error, module(), Reason}
                          when
                              XrefServer :: xref(),
                              LibraryPath :: library_path(),
                              Reason ::
                                  {file_error, file(), file_error()} |
                                  {invalid_options, term()} |
                                  {invalid_path, term()}.

Equivalent to set_library_path(XrefServer, LibraryPath, []).

set_library_path(XrefServer, LibraryPath, Options)

-spec set_library_path(XrefServer, LibraryPath, Options) -> ok | {error, module(), Reason}
                          when
                              XrefServer :: xref(),
                              LibraryPath :: library_path(),
                              Options :: Option | [Option],
                              Option :: {verbose, boolean()} | verbose,
                              Reason :: {invalid_options, term()} | {invalid_path, term()}.

Sets the library path.

If the given path is a list of directories, the set of library modules is determined by choosing the first module encountered while traversing the directories in the given order, for those modules that occur in more than one directory. By default, the library path is an empty list.

The library path code_path is used by the functions m/1 and d/1, but can also be set explicitly. However, note that the code path will be traversed once for each used library module while setting up module data. On the other hand, if there are only a few modules that are used but not analyzed, using code_path may be faster than setting the library path to code:get_path/0.

If the library path is set to code_path, the set of library modules is not determined, and the info functions will return empty lists of library modules.

start(NameOrOptions)

-spec start(NameOrOptions) -> {ok, pid()} | {error, {already_started, pid()}}
               when
                   NameOrOptions :: Name | Options,
                   Name :: atom(),
                   Options :: Option | [Option],
                   Option :: {xref_mode, mode()} | term().

Creates an Xref server.

The process can optionally be given a name. The default mode is functions. Options that are not recognized by Xref are passed on to gen_server:start/4.

start(Name, Options)

-spec start(Name, Options) -> {ok, pid()} | {error, {already_started, pid()}}
               when Name :: atom(), Options :: Option | [Option], Option :: {xref_mode, mode()} | term().

Creates an Xref server with a given name.

The default mode is functions. Options that are not recognized by Xref are passed on to gen_server:start/4.

stop(XrefServer)

-spec stop(XrefServer) -> stopped when XrefServer :: xref().

Stops an Xref server.

update(XrefServer)

-spec update(XrefServer) -> {ok, Modules} | {error, module(), Reason}
                when
                    XrefServer :: xref(),
                    Modules :: [module()],
                    Reason :: {module_mismatch, module(), ReadModule :: module()} | add_mod_rsn().

Equivalent to update(XrefServer, []).

update(XrefServer, Options)

-spec update(XrefServer, Options) -> {ok, Modules} | {error, module(), Reason}
                when
                    XrefServer :: xref(),
                    Options :: Option | [Option],
                    Option :: {verbose, boolean()} | {warnings, boolean()} | verbose | warnings,
                    Modules :: [module()],
                    Reason :: {module_mismatch, module(), ReadModule :: module()} | add_mod_rsn().

Replaces the module data of all analyzed modules the BEAM files of which have been modified since last read by an add function or update.

Application membership of the modules is retained, and so is the value of the builtinsoption. Returns a sorted list of the names of the replaced modules.

variables(XrefServer)

-spec variables(XrefServer) -> {ok, [VariableInfo]}
                   when
                       XrefServer :: xref(),
                       VariableInfo :: {predefined, [variable()]} | {user, [variable()]}.

Equivalent to variables(XrefServer, []).

variables(XrefServer, Options)

-spec variables(XrefServer, Options) -> {ok, [VariableInfo]}
                   when
                       XrefServer :: xref(),
                       Options :: Option | [Option],
                       Option :: predefined | user | {verbose, boolean()} | verbose,
                       VariableInfo :: {predefined, [variable()]} | {user, [variable()]}.

Returns a sorted lists of the names of the variables of an Xref server.

The default is to return only the user variables.