Joseph Kain bio photo

Joseph Kain

Professional Software Engineer learning Elixir.

Twitter LinkedIn Github

Elixir 1.1.1 has been recently released and the includes built in profiling support with mix profile.fprof. I decied to take this new command for a spin. I’ve used fprof before so I’ll desribe some of the differences about using the new mix version.

This will be a short post, but hopefully useful or interesting.

Results Format

I’m using my game of life implementation that I wrote about in the past. I had previously setup profiling options for this program, including support for fprof. There are some differences between the reporing when using fprof directly and with the new mix profile.fprof support. With mix, I’ve enabled all the options I used with fprof before, and here’s the output:

MIX_ENV=prod time mix profile.fprof --callers=true --sort=own --details -e "Profile.run_test"

                                                                  CNT    ACC (ms)    OWN (ms)
Total                                                            81526    1042.615    1031.268

Enum."-reduce/3-lists^foldl/2-0-"/3                               2900       0.000      38.851
Enum."-reduce/3-lists^foldl/2-0-"/3                               2900       0.000      38.333
Enum."-reduce/3-lists^foldl/2-0-"/3                               2900       0.000      37.715
Enum."-reduce/3-lists^foldl/2-0-"/3                               2900       0.000      37.498
Enum."-reduce/3-lists^foldl/2-0-"/3                               2900       0.000      36.128
Enum."-reduce/3-lists^foldl/2-0-"/3                               1010       0.000      13.145
Enum.reduce/3                                                      601     161.130       9.827
Enum.reduce/3                                                      601     161.082       9.593
Enum.reduce/3                                                      601     159.431       9.464
Enum.reduce/3                                                      601     160.294       9.230
Enum.reduce/3                                                      601     154.103       8.899
Enum.reduce/3                                                       20     829.270       4.894
  Enum."-reduce/3-lists^foldl/2-0-"/3                            18535    1625.310     253.577  <--
    Enum."-reduce/3-lists^foldl/2-0-"/3                           2900       0.000      38.851
    Enum."-reduce/3-lists^foldl/2-0-"/3                           2900       0.000      38.333
    Enum."-reduce/3-lists^foldl/2-0-"/3                           2900       0.000      37.715
    Enum."-reduce/3-lists^foldl/2-0-"/3                           2900       0.000      37.498
    Enum."-reduce/3-lists^foldl/2-0-"/3                           2900       0.000      36.128
    anonymous fn/3 in Enum.map/2                                   900     159.238      14.991
    anonymous fn/3 in Enum.map/2                                   900     158.584      14.887
    anonymous fn/3 in Enum.map/2                                   900     159.389      14.852
...

This is nice and readable. The anonymous functions are still a little hard to fillow but that’s just a problem with functions not having names. The data is organized is nice columns and easy to follow.

To contrast, here’s the direct fprof output:

% MIX_ENV=prod mix run -e "Profile.fprof"

%% Analysis results:
{  anlysis_options,
 [{callers, true},
  {sort, own},
  {totals, true},
  {details, true}]}.

%                                               CNT       ACC       OWN
[{ totals,                                     81530,  985.003,  977.102}].  %%%

{[{ {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   42.280},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   37.985},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   36.809},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   36.663},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   21.512},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},1010,    0.000,   12.211},
  { {'Elixir.Enum',reduce,3},                    601,  178.067,    9.724},
  { {'Elixir.Enum',reduce,3},                    601,  158.718,    9.110},
  { {'Elixir.Enum',reduce,3},                    601,  162.003,    9.077},
  { {'Elixir.Enum',reduce,3},                    601,  158.718,    9.006},
  { {'Elixir.Enum',reduce,3},                    601,   91.765,    5.222},
  { {'Elixir.Enum',reduce,3},                     20,  778.835,    3.958}],
 { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},18535, 1528.106,  233.557},     %
 [{ {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   42.280},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   37.985},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   36.809},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   36.663},
  { {'Elixir.Enum','-reduce/3-lists^foldl/2-0-',3},2900,    0.000,   21.512},
  { {'Elixir.Enum','-map/2-fun-0-',3},           900,  176.149,   16.459},
  { {'Elixir.Life','-list_of_neighbors/3-fun-0-',6}, 900,   59.302,   15.913},
  { {'Elixir.Enum','-map/2-fun-0-',3},           900,  160.314,   14.960},
  { {'Elixir.Enum','-map/2-fun-0-',3},           900,  157.062,   14.751},
  { {'Elixir.Enum','-map/2-fun-0-',3},           900,  157.090,   14.670},
...

This data is still organized in columns, kind of. The “{}” make things a little difficult to follow. It also has the “Elixir.” annotations because it’s in Erlang format.

Peronsally (i.e. as a person) I find the new mix form easier to read. But, if I were writing a program to process the output and transform it or analyze it then the standard fprof format would be preferable. Especially if was writing that program in Elixir or Erlang - the output from fprof is a set of Erlang terms. The results should be directly consumable by an Erlang or Elixir program.

In fact, I’m assuming that mix profile.fprof takes in this format and transforms it into the human readable format we see when the running the command.

If you want to setup standard fprof yourself see my older post Profiling Elixir. But if you just want human readable results the mix profile.fprof command will serve your well.

In might be interesting if a future version of mix profile.fprof had a variant that could return the raw analysis as an Elixir structure.

Next Week

That’s all for fprof for now.

Next week’s I’lldescribe some of the interesting talks I saw last week at Elixir Conf 2015.