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"}
]
end
This 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