Hello,
I've recently started reading and further exploring Erlang and Elixir's profiling tools and techniques. Of the three Erlang base profiling tools (
fprof,
eprof and
cprof), only
fprof has been implemented as a Mix Task so far (
fprof GitHub PR and
elixir-lang-core thread).
Rationale:
I believe eprof and cprof should also be added as a Mix Task (each) for the following reasons:
- Convenience: more convenient to run as a Mix Task than inside an IEx session or by other methods
- Standardisation: like said in the fprof elixir-lang-core thread it allows for easier inspection and pair debugging by issuing a standard command to retrieve results
- Developer Awareness: boosts awareness of Erlang/Elixir's profiling capabilities
- Purpose:
- Eprof - offers a different set of results and a different behaviour (as per the docs):
- Medium result set vs. Large result set of fprof: simpler to evaluate and comprehend when no deep profiling is necessary. Fprof adds other criteria like callers and garbage collection
- Small slowdown of the system being profiled vs. Significant slowdown of fprof: this helps achieve a result set closer to the actual running system and offers less downtime while profiling)
- Cprof - offers a call count behaviour where execution time is disregarded:
- Small and simple result
- Small slowdown
- Why not: I don't see why we should have one tool but not the others :)
I've searched here, in the GitHub repo and in the Elixir Forum and I didn't find any proposals or intentions of adding this feature.
Implementation:
I believe profile.eprof.ex and profile.cprof.ex implementations should be as close as possible to profile.fprof.ex (implementation) for greater readability and maintainability. However, a large part of profile.fprof.ex is dedicated to formatting and printing the results, which won't be necessary in profile.eprof.ex since it automatically pretty prints the results. This will be necessary in profile.cprof.ex as its results aren't pretty printed.
One possible pitfall I see is when running async code. Eprof's and cprof's APIs need to be used like so:
:eprof.start
:eprof.start_profiling(<list of processes>) # or :eprof.profile(...)
<code to be profiled here>
:eprof.stop_profiling
:eprof.analyze
and
:cprof.start(...)
<code to be profiled here>
:cprof.pause
:cprof.analyze
:cprof.stop
I believe not everything may be profiled if a certain async task/process is being ran and is not finished before telling the profiler to stop or pause. This should happen in both eprof and cprof, meaning certain time consuming tasks won't be counted in eprof and certain calls won't be counted in cprof.
This is also corroborated in eprof docs with the following statement:
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.
For most use cases I believe a script/Mix Task can be achieved, profiling functions/mfa's with sequential or synchronous code, specially regarding cprof. From what I've seen profile.fprof.ex also does not offer fprof's full API, but instead offers the options and behaviour which make sense in a Mix Task.
If this is accepted I'd like to give it a go at implementing one or both Mix Tasks during the next month or so. I'll probably start with cprof since it's the simplest tool.
Thanks!