· elixir debugging databases mysql

Elixir and Erlang Mysql Database Drivers

Yesterday, I was investigating the performance of database drivers in Erlang. Mysql performance on Erlang has never really been great. Emysql readme states a bunch of technical shortcomings, but then states it’s still probably the best one out there. Another one is erlang-mysql-driver, but it seems to have never gained any steam either. I’ve never heard of Erlmysql before today. Elixir has it’s own mysql driver Mariaex, but the performance of that isn’t that great. And Mysql-OTP is the newest one.

After benchmarking yesterday, Ecto seems like a good option for projects that want to remain database agnostic while writing in Elixir. I’m planning to open source a project, so it’s important for me to know that it will be performant. The only problem is that Mariaex seems to always takes 200ms to return a query even on repeated runs. The adoption of the mysql in a variety of stacks is huge, and a lot of people are very comfortable with it and won’t want to deploy or use Postgresql. For any sort of meaningful usage and adoption of a stack, both Postgres and Mysql need to be supported out of the box.

Making an alternative to Mariaex for Ecto

I spent some time debugging Mariaex, but that seems the harder route. Instead, I’ve wrapped the Mysql-OTP library to make it usable with Ecto. It’s on github as mysqlex. I chose that library as it seemed to be the easiest to wrap and get working out of the box. The results are below.

Results

The same general disclaimer applies to this benchmark as all others. It’s selecting two rows from a table. YMMV.

Note that using Ecto costs about 15% as compared to using the raw drivers for both mysqlex and postgrex. This, of course, will probably cost a lot more later with more complicated queries and loading of objects. The erlang postgres driver epgsql is also quite a bit faster than postgrex.

Standalone database performance doesn’t matter as much if the drivers don’t cut it. Mysql-otp is fairly new, but hopefully, it will hold up.

To use mysqlex with ecto, you’ll need to grab this gist for now: https://gist.github.com/tjheeta/800deab2b9e7b2b9651b

Raw results are below.

./wrk -c 100 -d 10 -t 20 http://localhost:8800/redis
Running 10s test @ http://localhost:8800/redis
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     8.37ms    1.70ms  38.77ms   89.57%
    Req/Sec   601.03     53.08   700.00     72.35%
  119860 requests in 10.05s, 25.49MB read
Requests/sec:  11922.39
Transfer/sec:      2.53MB

./wrk -c 100 -d 10 -t 20 http://localhost:8800/mysqlotp
Running 10s test @ http://localhost:8800/mysqlotp
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    10.14ms    2.33ms  48.78ms   89.50%
    Req/Sec   497.36     47.70   590.00     71.20%
  99189 requests in 10.03s, 21.47MB read
Requests/sec:   9887.67
Transfer/sec:      2.14MB

./wrk -c 100 -d 10 -t 20 http://localhost:8800/mysqlex 
Running 10s test @ http://localhost:8800/mysqlex
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    11.75ms    4.62ms 101.32ms   95.13%
    Req/Sec   436.97     60.93   540.00     80.75%
  87182 requests in 10.07s, 18.70MB read
Requests/sec:   8660.41
Transfer/sec:      1.86MB

./wrk -c 100 -d 10 -t 20 http://localhost:8800/epgsql
Running 10s test @ http://localhost:8800/epgsql
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    12.10ms    3.05ms  62.25ms   91.50%
    Req/Sec   418.17     41.91   515.00     77.50%
  83458 requests in 10.08s, 17.82MB read
Requests/sec:   8281.47
Transfer/sec:      1.77MB

# mysqlex
./wrk -c 100 -d 10 -t 20 http://localhost:8800/ecto   
Running 10s test @ http://localhost:8800/ecto
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    12.84ms    2.34ms  44.57ms   83.83%
    Req/Sec   391.24     35.26   484.00     69.80%
  78012 requests in 10.03s, 16.51MB read
Requests/sec:   7779.65
Transfer/sec:      1.65MB

./wrk -c 100 -d 10 -t 20 http://localhost:8800/emysql
Running 10s test @ http://localhost:8800/emysql
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    16.18ms   10.27ms 169.60ms   96.97%
    Req/Sec   327.49     55.30     1.11k    82.83%
  65382 requests in 10.09s, 13.90MB read
Requests/sec:   6477.24
Transfer/sec:      1.38MB

./wrk -c 100 -d 10 -t 20 http://localhost:8800/postgrex
Running 10s test @ http://localhost:8800/postgrex
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    18.53ms   15.12ms 256.30ms   97.98%
    Req/Sec   296.49     38.70   400.00     82.79%
  58653 requests in 10.04s, 12.70MB read
Requests/sec:   5844.39
Transfer/sec:      1.26MB
 
# postgrex
./wrk -c 100 -d 10 -t 20 http://localhost:8800/ecto 
Running 10s test @ http://localhost:8800/ecto
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    24.02ms   31.47ms 418.37ms   97.34%
    Req/Sec   257.29     37.97   320.00     84.66%
  50299 requests in 10.08s, 10.65MB read
Requests/sec:   4990.60
Transfer/sec:      1.06MB

./wrk -c 100 -d 10 -t 20 http://localhost:8800/mariaex
Running 10s test @ http://localhost:8800/mariaex
  20 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   200.59ms   18.58ms 223.10ms   97.92%
    Req/Sec    24.70      9.91    90.00     64.20%
  4947 requests in 10.04s, 1.06MB read
Requests/sec:    492.70
Transfer/sec:    108.26KB


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