HTTP Shooting Party

Here at reevoo we have been busy building an API for our data, part of this process involved a large refactoring of our core front end app reevoomark to use the new API.

Recently I have been looking for simple ways to improve the performance of this application and a quick look at new relic confirmed that we were spending a large proportion of our wallclock time connecting to our API over HTTP.

new relic application trace

Looking at the HTTP client we were using to connect to the API seemed like a great place to start making some performance improvements.

I decided to build some benchmarks to test the different libraries that are available, you can take a look at the code on github

The lists of clients I tested was by no means exhaustive but I think covers most of the currently popular options.

Methodology

Net::HTTP is the http library included in the ruby standard library, I have decided to use it as a performance baseline and compare the performance of the other libraries relative to net http.

The benchmarks involve downloading a static json file from an NGINX server, parsing the file to ensure the response is correct. We are repeating this process 1000 times in order to average out any minor jitters.

{ "foo" : "bar" }

In order to detect any transient issues each benchmark will be repeated 100 times and any outlying results will be investigated and / or disregarded.

We are running the benchmarks on a 2011 era MacPro with 8GB of ram and four cores, the OS is Ubuntu 14.04 and we are using the current stable version of ruby (2.1.2).

Some of the clients have support for persisent connections when the server supports http 1.1 keepalive, so we will repeat the benchmarks with and without this enabled.

Results

Results With No Keepalive

Curb and patron deliver some impressive results here, both are significantly faster in these tests than Net:HTTP. The result for HTTParty is to be expected as it is an API wrapping the Net::HTTP library. The result for excon is particularly disappointing, as several releases ago benchmarks were reporting numbers broadly comparable with curb and patron, without the dependency on libcurl.

Results With Keepalive

Enabling keepalives in NGINX saw some quite significant performance increases for Curb, Patron and Typhoeus. Net::HTTP and HTTParty have no support for persistent connections so don’t make any gains here. With keepalive enabled httpclient is almost as fast as Net:HTTP on these benchmarks.

Conclusions

If raw performance is important use curb or if you want to use faraday then go for patron Both of these libraries depend on libcurl so might be slightly harder to install on some systems.

Enabling Keepalive on your server makes a big differnce when using a client that supports it, especialy in situations close to this benchmarking scenario, a client making many requests of a backend server.

On Ubuntu these dependencies can be installed with sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev

Further Reading

Image attribution

  1. Ved skytebanen / At the shooting range from Municipal Archives of Trondheim