Skip to content

Instantly share code, notes, and snippets.

@pbyrne
Last active March 16, 2020 22:39
Show Gist options
  • Save pbyrne/5218411 to your computer and use it in GitHub Desktop.
Save pbyrne/5218411 to your computer and use it in GitHub Desktop.
Comparison of our core Rails app using Webrick, Puma, and Unicorn. Almost no effort was made to optimize either application server. Tests were performed on a MacBook Air using `siege` to hit the application homepage.

TL;DR

Unicorn was by far the best performing (5.94 trans/sec over the 1-minute test, 352 total). Puma (3.95 trans/sec, 235 total) appeared to perform no better than Webrick, despite the default behavior of using up to 16 threads. Perhaps increasing its worker count to the number of cores will improve its performance.

I've tried to run multiple Puma workers with the workers directive (per their sample documentaiton), but I receive errors about undefined method 'workers' for #<Puma::Configuration::DSL:0x007ffca4bde798>).

Webrick

Server

$ bundle exec rails server
[2013-03-21 20:43:04] INFO  WEBrick 1.3.1
[2013-03-21 20:43:04] INFO  ruby 1.9.3 (2012-11-10) [x86_64-darwin12.2.0]
[2013-03-21 20:43:04] INFO  WEBrick::HTTPServer#start: pid=12667 port=3000

Siege

$ siege -c5 -t1m -v -b 'http://localhost:3000/'
Transactions:		         242 hits
Availability:		      100.00 %
Elapsed time:		       59.47 secs
Data transferred:	        3.49 MB
Response time:		        1.22 secs
Transaction rate:	        4.07 trans/sec
Throughput:		        0.06 MB/sec
Concurrency:		        4.95
Successful transactions:         242
Failed transactions:	           0
Longest transaction:	        1.65
Shortest transaction:	        0.40

CPU

moderate CPU utilization for webrick

Puma

Server

$ bundle exec puma
Puma 1.6.3 starting...
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://0.0.0.0:9292

Siege

$ siege -c5 -t1m -v -b 'http://localhost:9292/'
Transactions:		         235 hits
Availability:		      100.00 %
Elapsed time:		       59.44 secs
Data transferred:	        3.39 MB
Response time:		        1.25 secs
Transaction rate:	        3.95 trans/sec
Throughput:		        0.06 MB/sec
Concurrency:		        4.96
Successful transactions:         235
Failed transactions:	           0
Longest transaction:	        2.48
Shortest transaction:	        0.24

CPU

moderate CPU utilization for puma

Unicorn

Server

$ cat config/unicorn.rb                               
worker_processes 4

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

$ bundle exec unicorn --config-file config/unicorn.rb
worker=2 ready
worker=1 ready
worker=0 ready
worker=3 ready

Siege

$ siege -c5 -t1m -v -b 'http://localhost:8080/'
Transactions:		         352 hits
Availability:		      100.00 %
Elapsed time:		       59.24 secs
Data transferred:	        5.08 MB
Response time:		        0.83 secs
Transaction rate:	        5.94 trans/sec
Throughput:		        0.09 MB/sec
Concurrency:		        4.96
Successful transactions:         352
Failed transactions:	           0
Longest transaction:	        8.22
Shortest transaction:	        0.41

CPU

complete CPU utilization for unicorn

TL;DR

Basically the same story. Unicorn processes 489 requests in the 1-minute test to Puma's 295 and Webrick's 320.

Note that we're getting 500s rendering the views here, because the app needs some updates to be able to run in Ruby 2.0, but the application server was working so it's at least a first approximation of the actual results.

Webrick

Server

$ bundle exec rails server
[2013-03-21 21:36:26] INFO  WEBrick 1.3.1
[2013-03-21 21:36:26] INFO  ruby 2.0.0 (2013-02-24) [x86_64-darwin12.2.0]
[2013-03-21 21:36:26] INFO  WEBrick::HTTPServer#start: pid=26497 port=3000

Siege

$ siege -c5 -t1m -v -b 'http://localhost:3000/'
Transactions:		           0 hits
Availability:		        0.00 %
Elapsed time:		       59.10 secs
Data transferred:	       20.08 MB
Response time:		        0.00 secs
Transaction rate:	        0.00 trans/sec
Throughput:		        0.34 MB/sec
Concurrency:		        4.96
Successful transactions:           0
Failed transactions:	         320
Longest transaction:	        1.53
Shortest transaction:	        0.00

CPU

moderate CPU utilization for webrick

Puma

Server

$ bundle exec puma
Puma 1.6.3 starting...
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://0.0.0.0:9292

Siege

$ siege -c5 -t1m -v -b 'http://localhost:9292/'
Transactions:		           0 hits
Availability:		        0.00 %
Elapsed time:		       59.15 secs
Data transferred:	       18.63 MB
Response time:		        0.00 secs
Transaction rate:	        0.00 trans/sec
Throughput:		        0.31 MB/sec
Concurrency:		        4.97
Successful transactions:           0
Failed transactions:	         295
Longest transaction:	        2.34
Shortest transaction:	        0.00

CPU

moderate CPU utilization for puma

Unicorn

Server

$ cat config/unicorn.rb                               
worker_processes 4

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

$ bundle exec unicorn --config-file config/unicorn.rb
worker=0 ready
worker=3 ready
worker=1 ready
worker=2 ready

Siege

$ siege -c5 -t1m -v -b 'http://localhost:8080/'
Transactions:		           0 hits
Availability:		        0.00 %
Elapsed time:		       59.35 secs
Data transferred:	       32.30 MB
Response time:		        0.00 secs
Transaction rate:	        0.00 trans/sec
Throughput:		        0.54 MB/sec
Concurrency:		        4.97
Successful transactions:           0
Failed transactions:	         489
Longest transaction:	        7.15
Shortest transaction:	        0.00

CPU

complete CPU utilization by Unicorn

@taniadaniela
Copy link

taniadaniela commented Jan 25, 2018

really cool info, thanks for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment