Syntaxi

Profile and Pry-Debugging Elixir

In my heart of hearts, I'm a 'printf' debugger, where my first solution to any problem is just throwing godawful amounts of puts in Ruby, prints in Python, IO.inspects in Elixir, console.log in Javascript, and whatever else I can do to generate a wall of text saying "OK HERE NOW" or "IT WORKED! GOT TO STEP 3".

Somewhat surprisingly, this doesn't always work, and that's where things like pry in Ruby come in. Elixir also has a pry command, which is pretty simple to use.

Pry-Debugging

require IEx; IEx.pry

And that's it. As far as I'm aware IEx's pry doesn't support any of the extra commands that Ruby's pry does (like whereami, find-method, etc...) but at least you can get a peek of what all the local variables in a method are. Which is super useful.

To get Elixir's pry working you have to run the script through IEx with using the -s flag. For tests, this means instead of mix test you do iex -S mix test. When the execution hits the IEx.pry call, IEx will prompt asking

  Request to pry #PID<0.315.0> at test/pry_test.exs:8. Allow? [Yn]

Once running, you'll be in a shell where you can access the local variables and inspect them or pass them around to different functions. Unfortunately, after a minute you'll get this error:

     ** (ExUnit.TimeoutError) test timed out after 60000ms. You can change the timeout:

       1. per test by setting "@tag timeout: x"
       2. per case by setting "@moduletag timeout: x"
       3. globally via "ExUnit.start(timeout: x)" configuration
       4. or set it to infinity per run by calling "mix test --trace"
          (useful when using IEx.pry)

     Timeouts are given as integers in milliseconds.

Thankfully, this explains what to do: Just change the command to iex -S mix test --trace and you'll avoid the timeout. Elixir's docs can really be 💯 sometimes. When you're done using IEx's pry, enter respawn in the console to continue where the program left off.

Profiling

Elixir 1.1 added the Fprof mix task, which formats profiling code a bit nicer than the default Erlang formatting. It's easy enough to use the wrapper method that the mix task uses to profile whatever snippet of code you want:

  Mix.Tasks.Profile.Fprof.profile(
    fn -> YourModule.method(a, b, c) end,
    [sort: "own", callers: true]
  )

The last param is the keyword list of arguments, which you are described in the docs for the Fprof mix task. I would like this to provide some more options so that it's more in line with ruby-prof, which can output in different formats so that it can be used by other tools, so hopefully someone else works on that before it becomes an itch that I have to scratch.

Anywho, I hope this helps you debug and optimize your stuff, weary Elixir searcher