DEV Community

Anil Kumar Maurya
Anil Kumar Maurya

Posted on

Why to use PUMA in production for your Rails App

If you are still using Unicorn, Thin or Passenger open source application server in production then this post is for you.

Point to note that Passenger Enterprise is different from Passenger open source, this post only talks about Passenger open source.

This Blog Post has very good comparison about features provided by Unicorn, Puma & Passenger

Alt Text

Point to note in this comparison is that PUMA is multithreaded and Passenger is multithreaded in only Enterprise edition

If you believe that multithreaded server is of no use because Ruby has GIL then you should read below snippet from Heroku Blog

Alt Text

Therefore Heroku recommends to use Puma in production

Alt Text

Infact, dev.to (this blogging platform) is hosted on Heroku and uses Puma in production

Puma is already battle tested by Heroku, Recently Gitlab also migrated to Puma from Unicorn

Alt Text

Read about Gitlab migration journey here

Puma really outshine other options when your application is dependent on lots of I/O operations.

I did some benchmark to compare Passenger open source & Puma performance

Configuration used during benchmarking

Passenger gem:

  • Version: 6.0.5
  • Workers count: 6 (Default)

Puma gem:

  • Version: 4.3.5
  • Workers count: 4
  • Threads count: 5 *5 threads per worker

Machine:
macOS Catalina, Dual-Core Intel Core i5, 8GB RAM

Benchmarking tool and configuration

Tool used: https://github.com/wg/wrk
Configuration:

  • Threads: 2
  • Connections: 100
  • Duration: 30 sec

When I/O operations are minimal

homes.json API perform one DB query and return back json data

Passenger benchmark:

Alt Text

536 requests per second

Puma benchmark:

Alt Text

883 requests per second

Take away
64% increase in number of requests served per second
Puma can serve 10,000 more requests in 30 seconds

When I/O operation increases

homes/1.json API performs 2 operations, one DB query and one network call and then return back json data
Network call is HTTP.get('https://facebook.com')

Passenger benchmark:

Alt Text

9 requests per second

Puma benchmark:

Alt Text

29 requests per second

Take away
Puma is 3x faster
Puma can serve 600 more requests in 30 seconds

How to set correct thread and worker count for Puma

Every Application is different therefore there is no universal Puma config which everyone can use.
You will have to try different combination of threads and workers count to find out which one is good for your application.
I created one gem https://github.com/anilmaurya/puma-benchmark which can help you in finding correct thread and worker count for your application.

Ref

  1. https://deliveroo.engineering/2016/12/21/unicorn-vs-puma-rails-server-benchmarks.html
  2. https://www.toptal.com/ruby/ruby-concurrency-and-parallelism-a-practical-primer

Top comments (2)

Collapse
 
juansecaro profile image
Juanse Caro

It would have been nice to see nginx configs for each case.

Also I would add that setting up Passenger is orders of magnitude easier that setting up Puma.

Collapse
 
sturpin profile image
Sergio Turpín

Great post! Thanks for sharing 🙏