
Puma, a fast concurrent web server for Ruby - bretpiatt
http://puma.io
======
sleepyhead
Anyone used Puma on Heroku? Is it as simple as [1] or is there more
configuration required [2] as is the case with Unicorn [3]?

[1] [http://blog.steveklabnik.com/posts/2013-02-24-using-puma-
on-...](http://blog.steveklabnik.com/posts/2013-02-24-using-puma-on-heroku)

[2] [http://www.subelsky.com/2012/10/setting-up-puma-rails-on-
her...](http://www.subelsky.com/2012/10/setting-up-puma-rails-on-heroku.html)

[3] [https://devcenter.heroku.com/articles/rails-
unicorn](https://devcenter.heroku.com/articles/rails-unicorn)

~~~
vicentereig
I'm actually using it in a small side-project I implemented a couple of weeks
ago. ([http://playas.io](http://playas.io)) It uses Rails 4 [0], JRuby 1.7.4,
postgresql with full text search, one dyno and 10 workers.

It is not the first time I'm using JRuby and Puma, I must say I'm pretty happy
with it.

I had enough with the official documentation, just tweaking the DB pool to fit
in the Rediscloud free version constraints. [1]

[https://devcenter.heroku.com/articles/concurrency-and-
databa...](https://devcenter.heroku.com/articles/concurrency-and-database-
connections)

[0]: You'll need to download JCE 6 Extensions to get Puma, JRuby 1.7.4 and
Rails 4 running in development:
[http://www.oracle.com/technetwork/java/javase/downloads/jce-...](http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html)

[1]: Rediscloud free version gives you 10 connections.

------
amarraja
Can someone with more webserver knowledge please explain how puma works from a
high level? I know very little about web servers so the following may not even
make sense!

I have looked at the source, and it appears a thread pool will listen to
incoming requests, and pass them to a reactor then move on to handle more
requests. Another thread polls the sockets and writes the data to the response
stream when ready. [Note: this all may be completely wrong!]

If the way the server works as above is correct, does it mean it's possible to
achieve event-loop-based levels of concurrent connections along with good old
CPU concurrency as well?

~~~
FooBarWidget
I'm one of the authors behind Phusion Passenger
([https://www.phusionpassenger.com/](https://www.phusionpassenger.com/)), a
polyglot web server for Ruby, Python and Node.js.

What you said is basically correct. And yes, it is possible to combine event
loops with threads in the way you described to get CPU concurrency as well.
Whether it is actually helpful depends on the use case. The Phusion Passenger
core is evented (similar to Nginx and Node.js) since version 4.0. We
considered a multithreaded-evented architecture as well, but it turned out to
be less beneficial than we hoped because the applications themselves use
plenty of CPU already, and because we rely on shared in-memory state for
proper load balancing between processes, thus having a source of contention.
In the end, the single-threaded evented architecture in Phusion Passenger
turned out to be more than enough.

~~~
cmbaus
How does Passenger deal with blocking I/O from applications if it is single
threaded? Does the entire event loop block while doing I/O?

~~~
FooBarWidget
There are two components at work. One is the Phusion Passenger core, which is
evented and uses only non-blocking I/O. At no point does the event loop block.

The other component is the Ruby application process. I believe you are talking
about this component.

Concurrency on the Ruby application process side is handled using two
strategies:

1\. Multiprocessing. 1 process per concurrent connection, with a buffering
layer. This is architecturally the same as how Unicorn works when behind an
Nginx reverse proxy.

2\. Multithreading. 1 thread per concurrent connection, possibly with multiple
processes. This is architecturally similar to Puma, though not entirely the
same. It should be noted that multithreading support is available in the
Enterprise version only.

------
mrinterweb
I like puma, but I thought it was interesting that the left passenger out of
their performance graphs. Seems odd to omit the most popular ruby application
server from the results.

~~~
chc
All of the servers listed here are standalone servers, while Passenger is a
module for existing servers. I don't really see why you couldn't include
Passenger here, but it seems like they're only comparing like to like, which I
guess is fair.

~~~
tinco
You can use Passenger as a standalone server too, it's called Passenger
Standalone. You can install it with 'gem install passenger', and run it by
running 'passenger start'.

~~~
gmac
(In which case it installs and fires up a copy of nginx behind the scenes).

------
JiPi
Out of curiosity, why today?

I mean, this is not new at all, there is no major version that was released
AFAIK...

This is great to share that though, just curious why it's on HN today? :)

Edit: typo fix.

~~~
waylonrobert
Agreed. I also recall seeing it on HN before, and not that long ago.

~~~
bretpiatt
You may have seen a recent comment, looks like the main page was posted a year
ago -- I relied on the URL duplicate checker when submitting it (it was new to
me today to come across and I wanted to see thoughts from the HN community on
it).

I ran a the search and found the previous:

    
    
       A modern, concurrent web server for ruby (puma.io)
       16 points by kachhalimbu 1 year ago | 2 comments | cached

~~~
JiPi
Fair enough. Just thought I might have missed something new and big! :)

------
j4mie
I'm not a Rubyist, but if I'm reading the section of the README that describes
the design [1] correctly, the closest Python equivalent (architecturally
speaking) is Waitress [2].

[1] [https://github.com/puma/puma#built-for-speed--
concurrency](https://github.com/puma/puma#built-for-speed--concurrency)

[2]
[http://docs.pylonsproject.org/projects/waitress/en/latest/de...](http://docs.pylonsproject.org/projects/waitress/en/latest/design.html)

------
facorreia
Looks good. It would be nice to see it on the Web Framework Benchmarks
([https://github.com/TechEmpower/FrameworkBenchmarks](https://github.com/TechEmpower/FrameworkBenchmarks)).

Edit: someone created an issue asking for contributors:
[https://github.com/TechEmpower/FrameworkBenchmarks/issues/45...](https://github.com/TechEmpower/FrameworkBenchmarks/issues/459)

------
chucknelson
Any reason why thin is not in the comparison? Is it not very fast compared to
the others in the chart?

------
itsmeduncan
We (ShopKeep) are using Puma for our thin web-services around our platform.
Specifically, we send all of our data to a two nodes load-balanced running
Puma for our analytics aggregation. It's pretty amazing how a single instance
running Puma replaces an entire cluster of Unicorn workers.

p.s. We are also hiring Ruby, and iOS folks. Contact information is in my
profile.

------
purephase
I've been using Puma in dev/QA and it's impressive. I'm planning on trying it
out in production but have a lot invested in Unicorn at the moment. For
example, I have monit confs that kill workers once they reach a certain memory
threshold and I'll have to figure out how to do that with Puma.

------
FooBarWidget
I'm one of the authors behind Phusion Passenger
([https://www.phusionpassenger.com/](https://www.phusionpassenger.com/)), a
polyglot web server for Ruby, Python and Node.js.

We've recently written a comprehensive comparison between Puma and Phusion
Passenger, which you can read here:
[https://github.com/phusion/passenger/wiki/Puma-vs-Phusion-
Pa...](https://github.com/phusion/passenger/wiki/Puma-vs-Phusion-Passenger)
The comparison covers things like concurrency models, I/O models, security,
clustering, multi-app support, documentation, memory usage, performance and
more. Although the comparison is between Puma and Phusion Passenger, a lot of
the points are relevant to a Unicorn-Puma comparison as well.

~~~
moe
Please stop making your comparisons sound as if passenger-free was a fully
functional application server such as unicorn or puma. It is not.

Passenger-free is a deliberately crippled demo-version. If someone wants to
use passenger in production they will have to pay $50 USD per year, per server
for it. And you know that very well.

The 'free' passenger drops requests and serves 502 errors to the users during
_every single deploy_.

That's equivalent to popping up shareware nag-screens into my face at random
intervals. Except phusion passenger doesn't nag _me_ , it nags _my customers_.

You call the avoidance of these errors a 'feature' ('rolling restarts') that
must be paid for.

For some reason your helpful comparisons never mention that both unicorn[1]
and puma[2] ship with this basic functionality out of the box. One could
almost think it is part of your sales strategy to have people notice this
little 'limitation' only after they already deployed your product to
production...

[1] [http://www.justinappears.com/blog/2-no-downtime-deploys-
with...](http://www.justinappears.com/blog/2-no-downtime-deploys-with-
unicorn/)

[2] [http://blog.nicolai86.eu/posts/2013-02-06/phased-restarts-
us...](http://blog.nicolai86.eu/posts/2013-02-06/phased-restarts-using-puma)

~~~
trustfundbaby
I think thats a little harsh.

I've been using Passenger since it was called Apache mod_rails
[http://www.concept47.com/austin_web_developer_blog/ruby-
on-r...](http://www.concept47.com/austin_web_developer_blog/ruby-on-rails/mod-
rails-passenger-20-rc2-released-even-more-stable/) you have to remember that
before the Phusion guys showed up, there was no easy way to run a rails server
without proxying requests to mongrel, thin or something like that. instances
could bloat in memory or die and your app could, for whatever reason, go down
and you wouldn't know it. Did I mention that rails apps were also pretty slow
back then?

They made deploying and maintaining rails an order of magnitude easier with
Passenger, first with the mindblowingly simple installation process and later
by introducing ideas like killing and spinning up new app instances after xxx
requests, or spinning instances up or down depending on activity. All this
with simple configuration switches out the box. Even the advances in Passenger
4 are pretty amazing (threaded mode, and out-of-band garbage collection, come
to mind)

What I'm saying is, they've done __a lot __for the Rails ecosystem and while I
'm not a fan of their new pricing strategy with Passenger or their marketing
tack with Puma posts on this thread, I think its worthwhile to be a bit more
gentle in chiding them because of their peerless contributions in the past ...
plus their link is actually a very well written comparison

~~~
moe
Yes, phusion was a viable contender for a brief timeframe. That was 5 years
ago, in 2008, until unicorn came around in 2009.

I don't see how their standing in 2008 excuses them to use shady trojan horse
sales tactics to push their rather mediocre product in 2013.

~~~
FooBarWidget
Unicorn improved upon Mongrel in many ways, and it is interesting technology.
We know, because we are Unicorn contributors ourselves (take a look at the
AUTHORS file). However Phusion Passenger did not stay behind. Since the
introduction of Unicorn, we introduced Phusion Passenger Standalone, which
allows you to use Phusion Passenger in a Unicorn-like manner (e.g. you can
attach it to an Nginx reverse proxy, and it uses a Unicorn-like architecture).
Since then, we've even improved upon Unicorn. For example, the out-of-band
garbage collection that Unicorn has? We've made it better with out-of-band
work. Administration tools for querying the status of workers? passenger-
status and passenger-memory-stats do it better than Unicorn. Python support?
Not in Unicorn. And so on.

Phusion Passenger is used to full satisfaction by many large parties, such as
Motorola, UPS, Hitachi, etc. So if you can point out technical reasons why you
think our product is "mediocre", please feel free to tell us, and we'll fix
them.

------
JiPi
Just keep in mind your code (and gem's code) needs to be thread safe.

------
allr
Less memory usage then Unicorn here, though we recently moved to Passenger
enterprise which is really similar:
[https://www.phusionpassenger.com/enterprise](https://www.phusionpassenger.com/enterprise)

good writeup on the subject here:
[https://github.com/phusion/passenger/wiki/Puma-vs-Phusion-
Pa...](https://github.com/phusion/passenger/wiki/Puma-vs-Phusion-Passenger)

------
justkez
I've been enjoying using Puma in clustered mode for some production sites, but
falling back to Thin for Server Sent Events (new EventSource()) - does anyone
know if this is ever likely to come to Puma, or is there a fundamental reason
that the Puma process model can't support SSE?

~~~
cmer
Are you doing so with MRI/Ruby 2.0? Been considering Puma over Unicorn since
it works so well for one of our JRuby apps but was wondering about how it
would perform on MRI since it seems like it was never really designed with MRI
in mind.

~~~
jrochkind1
When I tried to benchmark a standardized app under MRI, I found that Puma
works great _if_ your app is io-bound as opposed to cpu-bound.

This makes sense because multi-threading is still a win under MRI even with
the GIL, only so long as your app is io-bound (so threads can be switched out
when waiting on io, for instance waiting on a db query).

Most web apps I've worked with tend to be io-bound.

[https://github.com/jrochkind/fake_work_app/blob/master/READM...](https://github.com/jrochkind/fake_work_app/blob/master/README.md)

------
Bharath1234
Well. I have just come across this one which says Unicorn to be the best
performing one. Apparently, Puma proves wrong even with multiple workers.

[https://gist.github.com/pbyrne/5218411](https://gist.github.com/pbyrne/5218411)

~~~
Bjoern
Interesting goes against directly what they claim on their own page. Its
tested on a four core machine. I'm suspecting the 16 default threads were the
problem, since Unicorn only ran with 4 processes not 16.

[http://puma.io/](http://puma.io/)

------
gavingmiller
Can anyone who's used Puma on Heroku comment on how it compares to Unicorn?

~~~
enoptix
Much better memory usage and (for us at least) better concurrency. We could
only run 4 unicorn workers on a single dyno. But with Puma we run 16 threads
with ease.

~~~
nixme
Have you tried running 3 or even 4 puma workers (each with 8-16) threads on a
dyno? That way you can get more concurrency on CPU-bound requests in addition
to IO-bound concurrency (assuming MRI).

~~~
jrochkind1
I tried that in my attempt at benchmarking a standardized app on heroku, and,
yep, it works great:

[https://github.com/jrochkind/fake_work_app/blob/master/READM...](https://github.com/jrochkind/fake_work_app/blob/master/README.md)

------
FatalBaboon
I'm running Puma on my RaspberryPi for a pet Rails app and it's incredibly
fast. Would recommend.

------
perssontm
Is it just me beeing blind, or does it not support https?

~~~
FooBarWidget
It supports https through Nginx. HTTPS terminates at Nginx.

------
WayneDB
Puma is not for me, but Ragel seems very interesting.

