One of the things I was always intrigued about was CPU usage in data centers. I started developing web applications with Grails and then I moved on to Rails. It’s undeniable that both these frameworks provide the tools and abstractions to make life easier. The latter has served me well during the last few years, as it has Onfido, where our core systems are Rails-based.
One thing I’ve noticed is that CPU usage on the servers where Rails applications are deployed is quite low. But it seems this is not a problem exclusive to Rails applications. To confirm my suspicions, a while back I came across this post that highlights the underutilization of hardware resources in data centers.
More often than not we deploy our Rails applications coupled with some form of background processing capability – Resque, Sidekiq – and we are actually creating copies of our application, which increases memory usage. The efficiency gain in CPU usage is nowhere comparable to the amount of memory consumed by those instances. To this end, Elixir, standing on the shoulders of the Erlang VM giant, has always impressed me with its capability to use the system’s available resources efficiently.
Last week I got my Raspberry Pi 2 model B. It has a 900MHz quad-core ARM-A7 CPU and to be honest the first thing I thought when it arrived was: how would Elixir perform on it? To answer that question I first needed to get Erlang 17 installed. The Debian Erlang pre-compiled packages for the arm platform (I’m using Raspbian) are for the Erlang 15 version so it was time to compile Erlang !
I followed these steps on my Raspbian system to have Erlang 17 compiled with HiPE:
⁃ sudo apt-get update
⁃ sudo apt-get install wget
⁃ sudo apt-get install libssl-dev
⁃ sudo apt-get install ncurses-dev
⁃ sudo apt-get install m4
⁃ wget http://www.erlang.org/download/otp_src_17.4.tar.gz
⁃ tar -xzvf otpsrc17.4.tar.gz ⁃ cd otpsrc17.4/
⁃ sudo make install
I was prepared to wait for a few hours but I had a good surprise as the compilation time was 37 minutes!
With Erlang up and running the next step was to install Elixir. I used a precompiled package (precompiled zip file for the latest release) and after adding elixir bin path to my PATH environment variable, I was finally able to boot up an IEx session. Now it was time to see how the Pi 2 would behave as a server!
Raspbian running Phoenix Framework
I created a phoenix application and after consolidating the protocols I started the it in a named node in order to be able to monitor it with Observer from another machine. I used the monitoring machine to trigger requests using wrk. Ran some tests for 5 minutes with 25 threads and 25 open http connections. Here are a few screenshots of the results:
Pi2 system info
Pi2 load charts
wrk command output
Even though it was serving a simple html page I am really happy with the results. 540 requests per second on a $35 piece of hardware using on average 90% of the CPU and only 16 Mb memory beats my definition of efficiency!
For those of you interested in trying out Elixir on the Raspberry Pi 2, here is a 32 Gb sdcard image of raspbian with erlang 17 and elixir 1.0.3 installed.
Next step: buy some more Raspberry Pi 2s and build an Elixir cluster!