· elixir debugging databases mysql

Profiling and Debugging in Elixir - Mariaex

I’m looking for a solid mysql driver for Ecto. Mariaex is the only one, but it is behaving strangely and slowly. I’m documenting this debugging in hopes it is useful for future generations.

The raw results are below and the source code for this is on github.

Repeatedly running the benchmark has the latency pinned at 200 ms. This doesn’t make any sense.

# Ecto with Mariaex
./wrk -c 100 -d 10 -t 20 http://localhost:8800/mariaex
Running 10s test @ http://localhost:8800/ecto
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   200.42ms   20.91ms 223.84ms   97.64%
    Req/Sec    24.78      9.38    80.00     69.58%
  4950 requests in 10.04s, 1.05MB read
Requests/sec:    493.13
Transfer/sec:    106.91KB

Setting up a profiler with ExProf:

defmodule MariaProfile  do
  import ExProf.Macro

  @doc "analyze with profile macro"
  def do_analyze do
    c=[ hostname: "10.0.3.82", database: "test", username: "test", password: "test" ]
    {:ok, p} = Mariaex.Connection.start_link(c)
    profile do
      Mariaex.Connection.query(p, "SELECT id, name FROM domains")
    end
  end

  @doc "get analysis records and sum them up"
  def run do
    records = do_analyze
    total_percent = Enum.reduce(records, 0.0, &(&1.percent + &2))
    IO.inspect "total = #{total_percent}"
  end
end

And the results of MariaProfile.run:


FUNCTION                                        CALLS      %  TIME  [uS / CALLS]
--------                                        -----    ---  ----  [----------]
# skipping output 
lists:reverse/1                                     1   3.77     4  [      4.00]
erlang:monitor/2                                    1   3.77     4  [      4.00]
code_server:call/2                                  1   7.55     8  [      8.00]
'Elixir.String.Unicode':do_rstrip/3                29   9.43    10  [      0.34]
'Elixir.MariaProfile':'-do_analyze/0-fun-0-'/1      1   8.64     7  [      7.00]
erlang:send/3                                       1  18.87    20  [     20.00]

Something doesn’t add up here. Setting up a trace to on just what the Mariaex.Connection.query is doing:

iex(14)> :dbg.tracer
{:ok, #PID<0.1460.0>}
iex(15)> c=[ hostname: "10.0.3.82", database: "test", username: "test", password: "test" ]
[hostname: "10.0.3.82", database: "test", username: "test", password: "test"]
iex(16)> {:ok, p} = Mariaex.Connection.start_link(c)
{:ok, #PID<0.1464.0>}
iex(17)> :dbg.p(p) 
{:ok, [{:matched, :nonode@nohost, 1}]}

And the result:

iex(19)> Mariaex.Connection.query(p,"select id from domains limit 1");
(<0.1464.0>) << {'$gen_call',{<0.498.0>,#Ref<0.0.1.129562>},
                             {query,<<"select id from domains limit 1">>,[],
                                    []}}
(<0.1464.0>) << {inet_reply,#Port<0.12988>,ok}
(<0.1464.0>) << {tcp,#Port<0.12988>,
                     <<12,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,44,0,0,2,3,100,101,
                       102,4,116,101,115,116,7,100,111,109,97,105,110,115,7,
                       100,111,109,97,105,110,115,2,105,100,2,105,100,12,63,0,
                       20,0,0,0,8,39,66,0,0,0,5,0,0,3,254,0,0,2,0>>}
(<0.1464.0>) << {inet_reply,#Port<0.12988>,ok}
(<0.1464.0>) << {tcp,#Port<0.12988>,
                     <<1,0,0,1,1,44,0,0,2,3,100,101,102,4,116,101,115,116,7,
                       100,111,109,97,105,110,115,7,100,111,109,97,105,110,
                       115,2,105,100,2,105,100,12,63,0,20,0,0,0,8,39,66,0,0,0,
                       5,0,0,3,254,0,0,34,0,10,0,0,4,0,0,1,0,0,0,0,0,0,0,5,0,
                       0,5,254,0,0,34,0>>}
(<0.1464.0>) <0.498.0> ! {#Ref<0.0.1.129562>,
                          {ok,#{'__struct__' => 'Elixir.Mariaex.Result',
                                columns => [<<"id">>],
                                command => select,
                                last_insert_id => nil,
                                num_rows => 1,
                                rows => [{1}]}}}
(<0.1464.0>) << {inet_reply,#Port<0.12988>,ok}
{:ok,
 %Mariaex.Result{columns: ["id"], command: :select, last_insert_id: nil,
  num_rows: 1, rows: [{1}]}}

We would have to dig a bit deeper, perhaps by setting up traces to see what’s happenning, but I just can’t go down that rabbit hole.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket