EZProfiler.Manager (ezprofiler_deps v1.0.0)
This module requires the ezprofiler escript, see...
https://github.com/nhpip/ezprofiler.git
https://hex.pm/packages/ezprofiler
https://hexdocs.pm/ezprofiler/api-reference.html
This module provides the ability to perform code profiling programmatically within an application rather than via the ezprofiler CLI.
This maybe useful in environments where shell access maybe limited. Instead the output can be redirected to a logging subsystem for example.
Use of this module still requires the ezprofiler escript, but it will be automatically initialized in the background.
ezprofiler can be downloaded from https://github.com/nhpip/ezprofiler or added to deps in mix.exs along with this package:
defp deps do
[
{:ezprofiler, git: "https://github.com/nhpip/ezprofiler.git"},
{:ezprofiler_deps, git: "https://github.com/nhpip/ezprofiler_deps.git"}
]
endThis profiling mechanism supports two modes of operation, synchronous and asynchronous
In synchronous mode the user starts profiling and then calls a blocking call to wait for the results.
In asynchronous mode the results are sent as a message, this will be a handle_info/2 in the case of a GenServer
synchronous-example
Synchronous Example
EZProfiler.Manager.start_ezprofiler(%EZProfiler.Manager.Configure{ezprofiler_path: :deps})
...
...
with :ok <- EZProfiler.Manager.enable_profiling(),
:ok <- EZProfiler.Manager.wait_for_results(),
{:ok, filename, results} <- EZProfiler.Manager.get_profiling_results(true)
do
{:ok, filename, results}
else
rsp ->
rsp
end
...
...
EZProfiler.Manager.stop_ezprofiler()
asynchronous-example-as-a-genserver
Asynchronous Example as a GenServer
## Your handle_cast
def handle_cast(:start_profiling, state) do
EZProfiler.Manager.start_ezprofiler(%EZProfiler.Manager.Configure{ezprofiler_path: :deps})
EZProfiler.Manager.enable_profiling()
EZProfiler.Manager.wait_for_results_non_block()
{:noreply, state}
end
def handle_info({:ezprofiler, :results_available, filename, results}, state) do
EZProfiler.Manager.stop_ezprofiler()
do_something_with_results(filename, results)
{:noreply, state}
end
def handle_info({:ezprofiler, :results_available}, state) do
{:ok, filename, results} = EZProfiler.Manager.get_profiling_results(true)
EZProfiler.Manager.stop_ezprofiler()
{:noreply, state}
end
def handle_info({:ezprofiler, :timeout}, state) do
# Ooops
EZProfiler.Manager.stop_ezprofiler()
{:noreply, state}
end
Link to this section Summary
Functions
Disables code profiling. The equivalent of hitting r in the CLI.
Enables code profiling. The equivalent of hitting c or c label in the CLI.
Returns the resulting code profiling results. If the option display is set to true it will also output the stdout.
Starts and configures the ezprofiler escript. Takes the %EZProfiler.Manager.Configure{} struct as configuration.
Stops the ezprofiler escript. The equivalent of hitting q in the CLI.
Waits timeout seconds (default 60) for code profiling to complete.
This is an asynchronous version of wait_for_results/1. This will cause a message to be sent to the process id specified as the first argument.
Link to this section Types
display()
@type display() :: boolean()
filename()
@type filename() :: String.t()
label()
profile_data()
@type profile_data() :: String.t()
profiling_cfg()
@type profiling_cfg() :: EZProfiler.Manager.Configure.t()
self()
@type self() :: pid()
wait_time()
@type wait_time() :: integer()
Link to this section Functions
disable_profiling()
Disables code profiling. The equivalent of hitting r in the CLI.
enable_profiling(label \\ :any_label)
Enables code profiling. The equivalent of hitting c or c label in the CLI.
get_profiling_results(display \\ false)
@spec get_profiling_results(display() | false) :: {:ok, filename(), profile_data()} | {:error, atom()}
Returns the resulting code profiling results. If the option display is set to true it will also output the stdout.
On success it will return the tuple {:ok, filename, result_string}
start_ezprofiler(profiling_cfg \\ %Configure{})
@spec start_ezprofiler(profiling_cfg()) :: {:ok, :started} | {:error, :timeout} | {:error, :not_started}
Starts and configures the ezprofiler escript. Takes the %EZProfiler.Manager.Configure{} struct as configuration.
Most fields map directly onto the equivalent arguments for starting ezprofiler.
The exception to this is ezprofiler_path that takes the following options:
:system - if `ezprofiler` is defined via the `PATH` env variable.
:deps - if `ezprofiler` is included as an application in `mix.ezs`
path - a string specifying the full path for `ezprofiler`
example
Example
%EZProfiler.Manager.Configure{
cookie: nil,
cpfo: "false",
directory: "/tmp/",
ezprofiler_path: :system,
mf: "_:_",
node: nil,
profiler: "eprof",
sort: "mfa"
}
stop_ezprofiler()
Stops the ezprofiler escript. The equivalent of hitting q in the CLI.
wait_for_results(wait_time \\ 60)
@spec wait_for_results(wait_time() | 60) :: :ok | {:error, :timeout}
Waits timeout seconds (default 60) for code profiling to complete.
wait_for_results_non_block(pid \\ nil, wait_time \\ 60)
This is an asynchronous version of wait_for_results/1. This will cause a message to be sent to the process id specified as the first argument.
If no pid is specified the result is sent to self()
Three messages can be received:
{:ezprofiler, :results_available, filename, results}
{:ezprofiler, :results_available} # Needs to call `get_profiling_results/1`
{:ezprofiler, :timeout}In the case of a GenServer these will be received by handle_info/2