RealWorld Benchmark

This is a benchmark for a RealWorld back-end API implementation.

Recent results

I'm testing Rails, Go and Crystal implementations each on a separate START1-M Scaleway instance, which has following specs:

€7.99/mo
4 X86 64bit Cores
4GB memory
Ubuntu Xenial

Rails Configuration

Using Ruby 2.4.0:

git clone https://github.com/gothinkster/rails-realworld-example-app && cd rails-realworld-example-app
git fetch origin rails-5.1 && git checkout rails-5.1
bundle install
# Of course I had to install nokogiri, libsqlite3-dev and even NodeJS before running this monster. 
# Yes, I need NodeJS to run `rake db:migrate`... 2k18, guys
# Also in Gemfile there is `gem 'devise', git: 'https://github.com/gogovan/devise.git', branch: 'rails-5.1'`, which is 404
# Had to replace with `https://github.com/plataformatec/devise.git`
rake db:migrate
# Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Rails release the migration was written for:
Results
Rails and Ruby are dead for me.

Crystal configuration

A PostgreSQL instance was running in a single Docker container. 4 instances of the application were running in parallel due to Crystal's not supporting parallelism yet.

docker run --name postgres --restart unless-stopped -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=crystalworld -d postgres:9.5
git clone https://github.com/vladfaust/crystalworld.git && cd crystalworld
env APP_ENV=production shards build --production --release --no-debug
./bin/cake db:migrate

Then 4 times in separate terminals (may be overcome by Docker with reverse proxy or Dokku/Heroku with Procfile):

export APP_ENV=production DATABASE_URL=postgres://postgres:postgres@localhost:5432/crystalworld JWT_SECRET_KEY=064f42f6fea056b8c9c10f14973629c9b541879514a854f287298ecbf28a5c82
./bin/server

Then in another terminal:

git clone https://github.com/vladfaust/realworld-benchmark.git && cd realworld-benchmark
shards install
crystal src/realworld-benchmark.cr --release --no-debug --progress -- --host=localhost -p 5000
Results:
Testing Crystal HTTP::Client latency...
Crystal HTTP::Client latency: 140μs

Registering 100 users...
Overall time elapsed: 21.257s
Per user: 210.467ms
Per user minus latency: 210.326ms
RPS: 4.75

User#1 JWT token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjcnlzdGFsd29ybGQiLCJzdWIiOiJhdXRoIiwiZXhwIjoxNTMwMzYzODMxLCJ1c2VyIjp7ImlkIjoxfX0.EhXpYZINzEti7Y5i0Rj1ThqutLFX2MyeDyBTav7y6Uo

Creating 10000 articles...
Overall time elapsed: 1.46m
Per article: 8.742ms
Per article minus latency: 8.601ms
RPS: 116.27

Creating 0..5 comments per user
Created 233 comments
Overall time elapsed: 1.935s
Per comment: 8.303ms
Per comment minus latency: 8.163ms
RPS: 122.51

Creating 0..3 favorites per article
Created 14909 favorites
Overall time elapsed: 3.31m
Per favorite: 13.335ms
Per favorite minus latency: 13.194ms
RPS: 75.79

Creating 0..5 followings per users
Created 222 followings
Overall time elapsed: 1.752s
Per following: 7.892ms
Per following minus latency: 7.751ms
RPS: 129.01

Now running benchmarks with wrk...

Running Current User...
Running 30s test @ http://localhost:5000/user
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   178.25ms  221.33ms   1.03s    79.46%
    Req/Sec   175.74    149.41     0.88k    70.44%
  49204 requests in 30.09s, 17.41MB read
Requests/sec:   1635.10
Transfer/sec:    592.41KB

Running Single Article...
Running 30s test @ http://localhost:5000/articles/article-1-1
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   282.77ms  383.95ms   1.62s    80.29%
    Req/Sec   153.17     98.60   646.00     68.14%
  43213 requests in 30.09s, 14.63MB read
Requests/sec:   1436.15
Transfer/sec:    497.88KB

Running Articles by Author...
Running 30s test @ http://localhost:5000/articles?author=user1
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   301.94ms  191.54ms   1.13s    62.96%
    Req/Sec    30.70     14.32    89.00     69.49%
  9128 requests in 30.08s, 214.28MB read
  Socket errors: connect 0, read 0, write 0, timeout 48
Requests/sec:    303.45
Transfer/sec:      7.12MB

Running Articles by Tag...
Running 30s test @ http://localhost:5000/articles?tag=foo
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.26s   457.13ms   2.00s    63.29%
    Req/Sec     4.51      4.22    30.00     67.33%
  783 requests in 30.08s, 780.31MB read
  Socket errors: connect 0, read 0, write 0, timeout 546
Requests/sec:     26.03
Transfer/sec:     25.94MB

Running All Comments for Article...
Running 30s test @ http://localhost:5000/articles/article-1-1/comments
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   306.27ms  400.36ms   1.78s    80.26%
    Req/Sec    99.09     47.07   270.00     64.53%
  28702 requests in 30.09s, 18.07MB read
Requests/sec:    953.96
Transfer/sec:    614.86KB

Running Profile...
Running 30s test @ http://localhost:5000/profiles/user1
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   251.56ms  318.87ms   1.64s    80.51%
    Req/Sec   115.30     80.76   545.00     69.03%
  32411 requests in 30.08s, 5.56MB read
Requests/sec:   1077.34
Transfer/sec:    189.38KB

Running All Tags...
Running 30s test @ http://localhost:5000/tags
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.04s   471.94ms   1.99s    65.33%
    Req/Sec    17.20     15.32    60.00     68.54%
  201 requests in 30.10s, 28.06KB read
  Socket errors: connect 0, read 1, write 0, timeout 2
  Non-2xx or 3xx responses: 101
Requests/sec:      6.68
Transfer/sec:      0.93KB

Summary

The best result for Current User is 0.61ms, which is kinda good. DB is a weak spot for this implementation, Crystal itself takes 150-300μs in most of the requests.

Go

To be done...

Installation

It's a Crystal application, so you'll need to have Crystal installed on the machine. It also relies on wrk, which is mandatory.

Usage

crystal src/realworld-benchmark.cr --release --no-debug --progress -- --host=localhost -p 5000

Contributors