SlideShare a Scribd company logo
1 of 34
Download to read offline
Optimizing rails applications’
                                 performance
                               with Asset CDN and Unicorn

                                            Simon Bagreev, @status_200
                                                    sbagreev@gmail.com




Friday, January 11, 13
Question
                         Does anyone know what

                                 f5dd
                                  is?




Friday, January 11, 13
What This Preso is NOT

                         • not a coding demo or tutorial (strangely)
                         • not a best practices showcase




Friday, January 11, 13
What This Preso IS

                         • tips and tricks on tuning rails application
                         • personal experience




Friday, January 11, 13
Disclaimer
                         There are many other ways to improve app’s 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
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
Sample App




Friday, January 11, 13
NewRelic Monitoring




                         average load time for mobile traffic only, includes iframed ads




Friday, January 11, 13
Heroku Dyno Operation




Friday, January 11, 13
Step 1 - Rack::Cache




                  Serving assets from rack::cache is faster, and frees up app instance to serve more requests




Friday, January 11, 13
Static Asset Caching
                         # Gemfile
                         gem 'dalli'

                         # config/application.rb
                         config.cache_store = :dalli_store

                         # config/environments/production.rb
                         config.action_dispatch.rack_cache = {
                           :metastore    => Dalli::Client.new,
                           :entitystore => 'file:tmp/cache/rack/body',
                           :allow_reload => false
                         }
                         config.serve_static_assets = true
                         config.assets.digest = true

                         config.action_controller.perform_caching = true
                         # provision Memcache addon on Heroku




Friday, January 11, 13
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
Using Rack::Cache Effect




                         down from 4.91 / 201 / 2.29 before the change -- not bad for 8 lines of code!




Friday, January 11, 13
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
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
Now, on git push heroku




                         assets are automatically synced to s3 anytime ON rake assets:precompile




Friday, January 11, 13
S3 Bucket effect




                         down from 4.45 / 179 / 2.43 before the change -- even better!




Friday, January 11, 13
Step 3 - AWS CloudFront




Friday, January 11, 13
CloudFront Effect




                         down from 3.85 / 179 / 2.19 before the change -- Awesome!




Friday, January 11, 13
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
WebPageTest ResultsBefore




Friday, January 11, 13
WebPageTest Results After




Friday, January 11, 13
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
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
Unicorn for Rails App
                         # Gemfile
                         gem 'unicorn'

                         # Procfile
                         web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

                         # config/application.rb
                         config.logger = Logger.new(STDOUT)

                         # also, add config/unicorn.rb




Friday, January 11, 13
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
After Implementing Unicorn




                         down from 3.64 / 46.7 / 1.17 before the change -- good, but also...




Friday, January 11, 13
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
And ...




                         my app can process six concurrent requests on two heroku dynos




Friday, January 11, 13
Riding Unicorn




Friday, January 11, 13
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
Friday, January 11, 13
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
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

More Related Content

What's hot

Making Your Capistrano Recipe Book
Making Your Capistrano Recipe BookMaking Your Capistrano Recipe Book
Making Your Capistrano Recipe BookTim Riley
 
IT Infrastructure Through The Public Network Challenges And Solutions
IT Infrastructure Through The Public Network   Challenges And SolutionsIT Infrastructure Through The Public Network   Challenges And Solutions
IT Infrastructure Through The Public Network Challenges And SolutionsMartin Jackson
 
Puppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 EditionPuppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 EditionJoshua Thijssen
 
Islands: Puppet at Bulletproof Networks
Islands: Puppet at Bulletproof NetworksIslands: Puppet at Bulletproof Networks
Islands: Puppet at Bulletproof NetworksLindsay Holmwood
 
Scaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web ServicesScaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web ServicesAndrew Turner
 
Fixing Growing Pains With Puppet Data Patterns
Fixing Growing Pains With Puppet Data PatternsFixing Growing Pains With Puppet Data Patterns
Fixing Growing Pains With Puppet Data PatternsMartin Jackson
 
Performance Improvements in Browsers
Performance Improvements in BrowsersPerformance Improvements in Browsers
Performance Improvements in Browsersjeresig
 
Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點William Yeh
 
TorqueBox - When Java meets Ruby
TorqueBox - When Java meets RubyTorqueBox - When Java meets Ruby
TorqueBox - When Java meets RubyBruno Oliveira
 
Getting started with Ansible
Getting started with AnsibleGetting started with Ansible
Getting started with AnsibleIvan Serdyuk
 
JUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrinderJUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrindermarekgoldmann
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxbobmcwhirter
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...bobmcwhirter
 
Practicing Continuous Deployment
Practicing Continuous DeploymentPracticing Continuous Deployment
Practicing Continuous Deploymentzeeg
 
Challenges when building high profile editorial sites
Challenges when building high profile editorial sitesChallenges when building high profile editorial sites
Challenges when building high profile editorial sitesYann Malet
 
Practical Performance: Understand and improve the performance of your applica...
Practical Performance: Understand and improve the performance of your applica...Practical Performance: Understand and improve the performance of your applica...
Practical Performance: Understand and improve the performance of your applica...Chris Bailey
 
Scalable Systems Management with Puppet
Scalable Systems Management with PuppetScalable Systems Management with Puppet
Scalable Systems Management with PuppetPuppet
 
Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014
Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014
Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014zshoylev
 
Docker Online Meetup #3: Docker in Production
Docker Online Meetup #3: Docker in ProductionDocker Online Meetup #3: Docker in Production
Docker Online Meetup #3: Docker in ProductionDocker, Inc.
 

What's hot (20)

Making Your Capistrano Recipe Book
Making Your Capistrano Recipe BookMaking Your Capistrano Recipe Book
Making Your Capistrano Recipe Book
 
IT Infrastructure Through The Public Network Challenges And Solutions
IT Infrastructure Through The Public Network   Challenges And SolutionsIT Infrastructure Through The Public Network   Challenges And Solutions
IT Infrastructure Through The Public Network Challenges And Solutions
 
Puppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 EditionPuppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 Edition
 
Islands: Puppet at Bulletproof Networks
Islands: Puppet at Bulletproof NetworksIslands: Puppet at Bulletproof Networks
Islands: Puppet at Bulletproof Networks
 
Scaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web ServicesScaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web Services
 
Fixing Growing Pains With Puppet Data Patterns
Fixing Growing Pains With Puppet Data PatternsFixing Growing Pains With Puppet Data Patterns
Fixing Growing Pains With Puppet Data Patterns
 
Performance Improvements in Browsers
Performance Improvements in BrowsersPerformance Improvements in Browsers
Performance Improvements in Browsers
 
Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點Ansible 實戰:top down 觀點
Ansible 實戰:top down 觀點
 
TorqueBox - When Java meets Ruby
TorqueBox - When Java meets RubyTorqueBox - When Java meets Ruby
TorqueBox - When Java meets Ruby
 
Getting started with Ansible
Getting started with AnsibleGetting started with Ansible
Getting started with Ansible
 
JUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrinderJUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrinder
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Practicing Continuous Deployment
Practicing Continuous DeploymentPracticing Continuous Deployment
Practicing Continuous Deployment
 
Challenges when building high profile editorial sites
Challenges when building high profile editorial sitesChallenges when building high profile editorial sites
Challenges when building high profile editorial sites
 
Practical Performance: Understand and improve the performance of your applica...
Practical Performance: Understand and improve the performance of your applica...Practical Performance: Understand and improve the performance of your applica...
Practical Performance: Understand and improve the performance of your applica...
 
kubernetes practice
kubernetes practicekubernetes practice
kubernetes practice
 
Scalable Systems Management with Puppet
Scalable Systems Management with PuppetScalable Systems Management with Puppet
Scalable Systems Management with Puppet
 
Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014
Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014
Taming the Cloud Database with Apache jclouds, ApacheCon Europe 2014
 
Docker Online Meetup #3: Docker in Production
Docker Online Meetup #3: Docker in ProductionDocker Online Meetup #3: Docker in Production
Docker Online Meetup #3: Docker in Production
 

Viewers also liked

Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Justin Gordon
 
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Justin Gordon
 
xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012Justin Gordon
 
React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016Justin Gordon
 
Interactively Querying Large-scale Datasets on Amazon S3
Interactively Querying Large-scale Datasets on Amazon S3Interactively Querying Large-scale Datasets on Amazon S3
Interactively Querying Large-scale Datasets on Amazon S3Amazon Web Services
 
The Art of Product Marketing
The Art of Product MarketingThe Art of Product Marketing
The Art of Product MarketingRand Fishkin
 

Viewers also liked (7)

Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
 
React on rails v4
React on rails v4React on rails v4
React on rails v4
 
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
 
xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012xUnit and TDD: Why and How in Enterprise Software, August 2012
xUnit and TDD: Why and How in Enterprise Software, August 2012
 
React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016
 
Interactively Querying Large-scale Datasets on Amazon S3
Interactively Querying Large-scale Datasets on Amazon S3Interactively Querying Large-scale Datasets on Amazon S3
Interactively Querying Large-scale Datasets on Amazon S3
 
The Art of Product Marketing
The Art of Product MarketingThe Art of Product Marketing
The Art of Product Marketing
 

Similar to Improving Your Heroku App Performance with Asset CDN and Unicorn

Aloha on-rails-2009
Aloha on-rails-2009Aloha on-rails-2009
Aloha on-rails-2009John Woodell
 
Cloudcamp Athens 2011 Presenting Heroku
Cloudcamp Athens 2011 Presenting HerokuCloudcamp Athens 2011 Presenting Heroku
Cloudcamp Athens 2011 Presenting HerokuSavvas Georgiou
 
Introduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim SummitIntroduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim SummitRan Mizrahi
 
One Page, One App -or- How to Write a Crawlable Single Page Web App
One Page, One App -or- How to Write a Crawlable Single Page Web AppOne Page, One App -or- How to Write a Crawlable Single Page Web App
One Page, One App -or- How to Write a Crawlable Single Page Web Apptechnicolorenvy
 
Rails Application Optimization Techniques & Tools
Rails Application Optimization Techniques & ToolsRails Application Optimization Techniques & Tools
Rails Application Optimization Techniques & Toolsguest05c09d
 
Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...
Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...
Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...London Microservices
 
Red Dirt Ruby Conference
Red Dirt Ruby ConferenceRed Dirt Ruby Conference
Red Dirt Ruby ConferenceJohn Woodell
 
Puppet and AWS: Getting the best of both worlds
Puppet and AWS: Getting the best of both worldsPuppet and AWS: Getting the best of both worlds
Puppet and AWS: Getting the best of both worldsPuppet
 
Big Data & Cloud | Cloud Storage Simplified | Adrian Cole
Big Data & Cloud | Cloud Storage Simplified | Adrian ColeBig Data & Cloud | Cloud Storage Simplified | Adrian Cole
Big Data & Cloud | Cloud Storage Simplified | Adrian ColeJAX London
 
Embulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderEmbulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderSadayuki Furuhashi
 
Unleashing the Rails Asset Pipeline
Unleashing the Rails Asset PipelineUnleashing the Rails Asset Pipeline
Unleashing the Rails Asset PipelineKenneth Kalmer
 
Distributed Queue System using Gearman
Distributed Queue System using GearmanDistributed Queue System using Gearman
Distributed Queue System using GearmanEric Cho
 
Alfresco Environment Validation and "Day Zero" Configuration
Alfresco Environment Validation and "Day Zero" ConfigurationAlfresco Environment Validation and "Day Zero" Configuration
Alfresco Environment Validation and "Day Zero" ConfigurationAlfresco Software
 
Deployment with Fabric
Deployment with FabricDeployment with Fabric
Deployment with Fabricandymccurdy
 
Think_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptx
Think_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptxThink_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptx
Think_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptxPayal Singh
 
Apache Traffic Server
Apache Traffic ServerApache Traffic Server
Apache Traffic Serversupertom
 
Writing Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason LeeWriting Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason Leejaxconf
 
Mobile & Desktop Cache 2.0: How To Create A Scriptable Cache
Mobile & Desktop Cache 2.0: How To Create A Scriptable CacheMobile & Desktop Cache 2.0: How To Create A Scriptable Cache
Mobile & Desktop Cache 2.0: How To Create A Scriptable CacheBlaze Software Inc.
 

Similar to Improving Your Heroku App Performance with Asset CDN and Unicorn (20)

Aloha on-rails-2009
Aloha on-rails-2009Aloha on-rails-2009
Aloha on-rails-2009
 
Cloudcamp Athens 2011 Presenting Heroku
Cloudcamp Athens 2011 Presenting HerokuCloudcamp Athens 2011 Presenting Heroku
Cloudcamp Athens 2011 Presenting Heroku
 
Introduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim SummitIntroduction to node.js by Ran Mizrahi @ Reversim Summit
Introduction to node.js by Ran Mizrahi @ Reversim Summit
 
One Page, One App -or- How to Write a Crawlable Single Page Web App
One Page, One App -or- How to Write a Crawlable Single Page Web AppOne Page, One App -or- How to Write a Crawlable Single Page Web App
One Page, One App -or- How to Write a Crawlable Single Page Web App
 
Rails Application Optimization Techniques & Tools
Rails Application Optimization Techniques & ToolsRails Application Optimization Techniques & Tools
Rails Application Optimization Techniques & Tools
 
Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...
Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...
Lean microservices through ahead of time compilation (Tobias Piper, Loveholid...
 
Red Dirt Ruby Conference
Red Dirt Ruby ConferenceRed Dirt Ruby Conference
Red Dirt Ruby Conference
 
Puppet and AWS: Getting the best of both worlds
Puppet and AWS: Getting the best of both worldsPuppet and AWS: Getting the best of both worlds
Puppet and AWS: Getting the best of both worlds
 
Big Data & Cloud | Cloud Storage Simplified | Adrian Cole
Big Data & Cloud | Cloud Storage Simplified | Adrian ColeBig Data & Cloud | Cloud Storage Simplified | Adrian Cole
Big Data & Cloud | Cloud Storage Simplified | Adrian Cole
 
Embulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loaderEmbulk, an open-source plugin-based parallel bulk data loader
Embulk, an open-source plugin-based parallel bulk data loader
 
Unleashing the Rails Asset Pipeline
Unleashing the Rails Asset PipelineUnleashing the Rails Asset Pipeline
Unleashing the Rails Asset Pipeline
 
Rubypalooza 2009
Rubypalooza 2009Rubypalooza 2009
Rubypalooza 2009
 
Distributed Queue System using Gearman
Distributed Queue System using GearmanDistributed Queue System using Gearman
Distributed Queue System using Gearman
 
Alfresco Environment Validation and "Day Zero" Configuration
Alfresco Environment Validation and "Day Zero" ConfigurationAlfresco Environment Validation and "Day Zero" Configuration
Alfresco Environment Validation and "Day Zero" Configuration
 
Deployment with Fabric
Deployment with FabricDeployment with Fabric
Deployment with Fabric
 
Think_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptx
Think_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptxThink_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptx
Think_your_Postgres_backups_and_recovery_are_safe_lets_talk.pptx
 
RubyConf 2009
RubyConf 2009RubyConf 2009
RubyConf 2009
 
Apache Traffic Server
Apache Traffic ServerApache Traffic Server
Apache Traffic Server
 
Writing Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason LeeWriting Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason Lee
 
Mobile & Desktop Cache 2.0: How To Create A Scriptable Cache
Mobile & Desktop Cache 2.0: How To Create A Scriptable CacheMobile & Desktop Cache 2.0: How To Create A Scriptable Cache
Mobile & Desktop Cache 2.0: How To Create A Scriptable Cache
 

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 app’s 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
  • 8. NewRelic Monitoring average load time for mobile traffic only, includes iframed ads Friday, January 11, 13
  • 10. Step 1 - Rack::Cache Serving assets from rack::cache is faster, and frees up app instance to serve more requests Friday, January 11, 13
  • 11. Static Asset Caching # Gemfile gem 'dalli' # config/application.rb config.cache_store = :dalli_store # config/environments/production.rb config.action_dispatch.rack_cache = { :metastore => Dalli::Client.new, :entitystore => 'file:tmp/cache/rack/body', :allow_reload => false } config.serve_static_assets = true config.assets.digest = true config.action_controller.perform_caching = true # provision Memcache addon on Heroku 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 Effect 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 effect 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 Effect 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
  • 25. Unicorn for Rails App # Gemfile gem 'unicorn' # Procfile web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb # config/application.rb config.logger = Logger.new(STDOUT) # also, add config/unicorn.rb 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