Profiler v0.2.4 Profiler View Source

This sampling profiler is intendend for shell and remote shell usage. Most commands here print their results to the screen for human inspection.

Example usage:

iex(2)> Profiler.profile("<0.187.0>")
100% {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
  100% {IEx.Evaluator, :init, 4, [file: 'lib/iex/evaluator.ex', line: 27]}
    100% {IEx.Evaluator, :loop, 1, [file: 'lib/iex/evaluator.ex', line: 103]}
        100% {IEx.Evaluator, :eval, 3, [file: 'lib/iex/evaluator.ex', line: 217]}
          100% {IEx.Evaluator, :do_eval, 3, [file: 'lib/iex/evaluator.ex', line: 239]}
              100% {IEx.Evaluator, :handle_eval, 5, [file: 'lib/iex/evaluator.ex', line: 258]}
                100% {:elixir, :eval_forms, 3, [file: 'src/elixir.erl', line: 263]}
                    100% {:elixir, :recur_eval, 3, [file: 'src/elixir.erl', line: 278]}
                      100% {:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 680]}
                          100% {Profiler, :profile, 2, [file: 'lib/profiler.ex', line: 120]}
                            100% {Enum, :reduce_range_inc, 4, [file: 'lib/enum.ex', line: 3371]}
                                100% {Profiler, :"-profile/2-fun-0-", 3, [file: 'lib/profiler.ex', line: 121]}

Link to this section Summary

Functions

Demo function for the documentation. Never implement fibonacci like this. Never

This runs fprof the given amount of milliseconds or 5 seconds by default.

Processes lists all processes ordered by reductions withing the given timeout. For that it takes an initial snapshot, sleeps the given timeout and takes a second snapshot.

This runs the sampling profiler for the given amount of milliseconds or 10 seconds by default. The sampling profiler will collect stack traces of the given process pid or process name and print the collected samples based on frequency.

Arguments are the same as for profile() but this sampling profiler does not analyze stacktrace but instead just samples the current function and prints the result.

Returns current stacktrace for the given pid and allows setting the erlang internal stacktrace depth.

Times the given function and prints the result. Example usage

Link to this section Types

Link to this type

task()

View Source
task() :: String.t() | atom() | pid() | (... -> any())

Link to this section Functions

Demo function for the documentation. Never implement fibonacci like this. Never

Link to this function

fprof(pid, msecs \\ 5000)

View Source
fprof(task(), non_neg_integer()) :: binary()

This runs fprof the given amount of milliseconds or 5 seconds by default.

When the run completes the code tries to open kcachegrind to show the resultung kcachegrind file. Ensure to have kcachegrind installed. If kcachgrind is not found the function will just return the name of the generated report file. It can then be copied to another lcoation for analysis

For pid there are five different input formats allowed:

  1. fun() which will then be spwaned called in a loop and killed after the test
  2. Native pid()
  3. An atom that is resolved using whereis(name)
  4. A string of the format "" or "0.b.c" or just "b" in which case the pid is interpreted as "<0.b.0>"
  5. An integer, in which case the pid is interpreted as "<0.#{int}.0>"

    In this example the profiler is used to profile itself. The first percentage number shows how many samples were found in the given function call. Indention indicates the call stack:

  iex(1)> Profiler.fprof(fn -> Profiler.demo_fib(30) end)
Link to this function

processes(timeout \\ 5000)

View Source
processes(non_neg_integer()) :: :ok

Processes lists all processes ordered by reductions withing the given timeout. For that it takes an initial snapshot, sleeps the given timeout and takes a second snapshot.

  iex(1)> Profiler.processes
  [<0.187.0>,{'Elixir.IEx.Evaluator',init,4},1339]
  [<0.132.0>,tls_client_ticket_store,32]
  [<0.182.0>,{'Elixir.Logger.Watcher',init,1},1]
  [<0.181.0>,'Elixir.Logger.BackendSupervisor',1]
  [<0.180.0>,{'Elixir.Logger.Watcher',init,1},1]
  [<0.179.0>,'Elixir.Logger',1]
  [<0.178.0>,'Elixir.Logger.Supervisor',1]
  [<0.177.0>,{application_master,start_it,4},1]
  [<0.176.0>,{application_master,init,4},1]
  [<0.161.0>,'Elixir.Hex.UpdateChecker',1]
  :ok
Link to this function

profile(pid, n \\ 10000)

View Source
profile(task(), non_neg_integer()) :: :ok

This runs the sampling profiler for the given amount of milliseconds or 10 seconds by default. The sampling profiler will collect stack traces of the given process pid or process name and print the collected samples based on frequency.

For pid there are five different input formats allowed:

  1. fun() which will then be spwaned called in a loop and killed after the test
  2. Native pid()
  3. An atom that is resolved using whereis(name)
  4. A string of the format "" or "0.b.c" or just "b" in which case the pid is interpreted as "<0.b.0>"
  5. An integer, in which case the pid is interpreted as "<0.#{int}.0>"

    In this example the profiler is used to profile itself. The first percentage number shows how many samples were found in the given function call. Indention indicates the call stack:

  iex(2)> Profiler.profile(187)
  100% {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
    100% {IEx.Evaluator, :init, 4, [file: 'lib/iex/evaluator.ex', line: 27]}
      100% {IEx.Evaluator, :loop, 1, [file: 'lib/iex/evaluator.ex', line: 103]}
          100% {IEx.Evaluator, :eval, 3, [file: 'lib/iex/evaluator.ex', line: 217]}
            100% {IEx.Evaluator, :do_eval, 3, [file: 'lib/iex/evaluator.ex', line: 239]}
                100% {IEx.Evaluator, :handle_eval, 5, [file: 'lib/iex/evaluator.ex', line: 258]}
                  100% {:elixir, :eval_forms, 3, [file: 'src/elixir.erl', line: 263]}
                      100% {:elixir, :recur_eval, 3, [file: 'src/elixir.erl', line: 278]}
                        100% {:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 680]}
                            100% {Profiler, :profile, 2, [file: 'lib/profiler.ex', line: 120]}
                              100% {Enum, :reduce_range_inc, 4, [file: 'lib/enum.ex', line: 3371]}
                                  100% {Profiler, :"-profile/2-fun-0-", 3, [file: 'lib/profiler.ex', line: 121]}
Link to this function

profile_simple(pid, n \\ 10000)

View Source
profile_simple(task(), non_neg_integer()) :: :ok

Arguments are the same as for profile() but this sampling profiler does not analyze stacktrace but instead just samples the current function and prints the result.

The first number shows the total number of samples that have been recorded per function call.

For pid there are five different input formats allowed:

  1. fun() which will then be spwaned called in a loop and killed after the test
  2. Native pid()
  3. An atom that is resolved using whereis(name)
  4. A string of the format "" or "0.b.c" or just "b" in which case the pid is interpreted as "<0.b.0>"
  5. An integer, in which case the pid is interpreted as "<0.#{int}.0>"
  iex(2)> Profiler.profile_simple 197
  {10000, {Profiler, :"-profile_simple/2-fun-0-", 3}}
Link to this function

stacktrace(pid \\ nil, depth \\ 30)

View Source

Returns current stacktrace for the given pid and allows setting the erlang internal stacktrace depth.

Link to this function

time(fun, msg \\ "timer")

View Source
time((... -> any()), String.t()) :: any()

Times the given function and prints the result. Example usage:

  iex(1)> Profiler.time(fn() -> Process.sleep 1000 end)
  timer: 1004
  :ok