This document summarizes tips for optimizing the performance of Rails applications using asset CDNs and the Unicorn web server. It discusses using Amazon S3 and CloudFront for caching and delivering assets to improve load times. It also explains how to configure Unicorn to handle requests concurrently across worker processes to better utilize dyno resources on Heroku. Benchmark tests show these approaches reduced load times and increased the number of concurrent requests applications can handle.
1 of 34
Downloaded 27 times
More Related Content
Improving Your Heroku App Performance with Asset CDN and Unicorn
1. Optimizing rails applications
performance
with Asset CDN and Unicorn
Simon Bagreev, @status_200
sbagreev@gmail.com
Friday, January 11, 13
2. Question
Does anyone know what
f5dd
is?
Friday, January 11, 13
3. What This Preso is NOT
? not a coding demo or tutorial (strangely)
? not a best practices showcase
Friday, January 11, 13
4. What This Preso IS
? tips and tricks on tuning rails application
? personal experience
Friday, January 11, 13
5. Disclaimer
There are many other ways to improve apps performance:
?database performance (indexes, N+1, slow queries)
?caching
?background processing
?changing interpreter, GC
?conditional asset loading, etc
?removing cruft!
Try them first!
Friday, January 11, 13
6. This Presentation - Two Parts
? CDN Asset Host using aws*
? unicorn web server*
* Both approaches were tested on heroku, but must work with other hosting solutions
Friday, January 11, 13
12. After Deployment
should see entries like this in your log
cache: [GET /assets/application-c0747cab950350f59304a3815f980622.css] miss, store
cache: [GET /assets/application-032691d4988a7003c42a10995819a0ce.js] miss, store
cache: [GET /assets/s_code.js] miss, store
cache: [GET /assets/application-c0747cab950350f59304a3815f980622.css] fresh
cache: [GET /assets/application-032691d4988a7003c42a10995819a0ce.js] fresh
cache: [GET /assets/s_code.js] fresh
Friday, January 11, 13
13. Using Rack::Cache E?ect
down from 4.91 / 201 / 2.29 before the change -- not bad for 8 lines of code!
Friday, January 11, 13
14. Step 2 - S3 bucket for assets
heroku instance has more time to serve application code because all assets are served from aws s3
Friday, January 11, 13
15. S3 Bucket for Assets
# Gemfile
gem "asset_sync" # will push compiled assets into CDN
# Command line
heroku config:add FOG_PROVIDER=AWS
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=yyy
heroku config:add FOG_DIRECTORY=yourappname-assets
# config/environments/production.rb
config.action_controller.asset_host =
"//#{ENV['FOG_DIRECTORY']}.s3.amazonaws.com"
# make sure to use AssetTagHelper methods (like image_tag)
# to ensure assets are properly referenced
Friday, January 11, 13
16. Now, on git push heroku
assets are automatically synced to s3 anytime ON rake assets:precompile
Friday, January 11, 13
17. S3 Bucket e?ect
down from 4.45 / 179 / 2.43 before the change -- even better!
Friday, January 11, 13
18. Step 3 - AWS CloudFront
Friday, January 11, 13
19. CloudFront E?ect
down from 3.85 / 179 / 2.19 before the change -- Awesome!
Friday, January 11, 13
20. Loading Single File
$ time curl http://careersingear.mobi/assets/application-
bdb77a926724ccc3c20b923ab168d89d.js
real 0m0.896s
user 0m0.008s
sys 0m0.016s
----------------
$ time curl http://d3kd72psxbec02.cloudfront.net/assets/
application-bdb77a926724ccc3c20b923ab168d89d.js
real 0m0.293s
user 0m0.006s
sys 0m0.010s
getting a single application.js file from cloud front is 3x faster
Friday, January 11, 13
23. Meet Unicorn
? HTTp server for Ruby
? Starts one master process
? forks worker processes
? workers handle requests
? master returns
? one port, several
concurrent requests
Friday, January 11, 13
24. Server Setup
Unicorn setup
classic setup
nginx -> unix domain socket -> unicorn
nginx -> smart balancer -> pool of mongrels
workers (os handles load balancing)
Friday, January 11, 13
26. Unicorn for Rails App
# config/unicorn.rb
worker_processes 3
timeout 30
preload_app true
before_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
Rails.logger.info('Disconnected from ActiveRecord')
end
if defined?(Resque)
Resque.redis.quit
Rails.logger.info('Disconnected from Redis')
end
end
after_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
Rails.logger.info('Connected to ActiveRecord')
end
if defined?(Resque)
Resque.redis = ENV["REDISTOGO_URL"]
Rails.logger.info('Connected to Redis')
end
end
Friday, January 11, 13
27. After Implementing Unicorn
down from 3.64 / 46.7 / 1.17 before the change -- good, but also...
Friday, January 11, 13
28. Better Concurrency Handling
require 'typhoeus'
require "benchmark"
URL = "http://careersingear.mobi"
HYDRA = Typhoeus::Hydra.new(max_concurrency: 20)
1000.times do
request = Typhoeus::Request.new(URL, method: :get, timeout: 10000)
request.on_complete do |response|
puts response.code
end
HYDRA.queue(request)
end
Benchmark.bm(7) do |x|
x.report("first:") { HYDRA.run }
end
# using thin
# user system total real
# 1.030000 0.380000 1.410000 ( 16.713791)
# using unicorn
# user system total real
# 1.050000 0.390000 1.440000 ( 7.843766)
Friday, January 11, 13
29. And ...
my app can process six concurrent requests on two heroku dynos
Friday, January 11, 13
31. To Conclude
? implemented asset cdn
? configured unicorn
? brought down average end user load time from almost
5 sec to 3.5 sec
? app can serve more requests faster and for less $$$
Friday, January 11, 13
33. Credits
defunkt, unicorn! https://github.com/blog/517-unicorn
heroku dev center, using rack::cache with memcached in rails 3.1+ https://devcenter.heroku.com/articles/
rack-cache-memcached-rails31
Rice, david, using a cdn asset host with rails 3.1 https://devcenter.heroku.com/articles/cdn-asset-
host-rails31
Sikkes, Michael, Complete Guide to serving your Rails assets over S3 with asset_sync http://blog.firmhouse.com/
complete-guide-to-serving-your-rails-assets-over-s3-with-asset_sync
van roijen, michael, more concurrency on a single heroku dyno with the new celadon cedar stack http://
michaelvanrooijen.com/articles/2011/06/01-more-concurrency-on-a-single-heroku-dyno-
with-the-new-celadon-cedar-stack/
Friday, January 11, 13
34. Q&A
This presentation can be found on github github.com/semmin/asset-cdn-and-unicorn-preso
twitter: @status_200
Email: sbagreev@gmail.com
Questions?
Friday, January 11, 13