Accelerate Your Rails Site with Automatic Generation-Based Action Caching
Upcoming SlideShare
Loading in...5
×
 

Accelerate Your Rails Site with Automatic Generation-Based Action Caching

on

  • 2,999 views

 

Statistics

Views

Total Views
2,999
Views on SlideShare
2,989
Embed Views
10

Actions

Likes
1
Downloads
5
Comments
0

1 Embed 10

http://www.slideshare.net 10

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Accelerate Your Rails Site with Automatic Generation-Based Action Caching Accelerate Your Rails Site with Automatic Generation-Based Action Caching Presentation Transcript

  • Accelerate Your Rails Site with Automatic Generation-Based Action Caching Rod Cope, CTO and Founder OpenLogic, Inc. Wednesday, July 29, 2009
  • Goal Built-in caching is hard: Learn how to automate it to make the pain go away OpenLogic Company Confidential 2 Wednesday, July 29, 2009
  • Agenda Introduction Built-in caching Automatic generation-based caching Bonus material Conclusion & recommendations OpenLogic Company Confidential 3 Wednesday, July 29, 2009
  • Introduction Rod Cope CTO & Founder of OpenLogic 25 years of software development experience IBM Global Services, Anthem, Ericsson, many more OpenLogic, Inc. Governance, SLA support, security updates, and indemnification for over 500 Open Source packages Dozens of Fortune 500 customers OSS Census (osscensus.org) Global, community effort to catalog use of open source OpenLogic Company Confidential 4 Wednesday, July 29, 2009
  • No Spoon Feeding OpenLogic Company Confidential 5 Wednesday, July 29, 2009
  • Don’t Panic scotduke.com OpenLogic Company Confidential 6 Wednesday, July 29, 2009
  • Reasons for Caching Lots of hits, speed is king Google OpenLogic Company Confidential 7 Wednesday, July 29, 2009
  • OpenLogic Company Confidential 8 Wednesday, July 29, 2009
  • Reasons for Caching Lots of hits, speed is king Google Complex hits, richness is king OpenLogic’s OLEX OpenLogic Company Confidential 9 Wednesday, July 29, 2009
  • OpenLogic Company Confidential 10 Wednesday, July 29, 2009
  • Rails Caching Background Page caching Uberfast, little control Highly dynamic site? Move on. Action caching Fast, lots of control Expiration hell Fragment caching Expiration hell OpenLogic Company Confidential 11 Wednesday, July 29, 2009
  • Problems with Rails Caching Caching is easy to implement “Site’s borked again - turn off caching.” Hard to clear (the right) caches when you’re mixing and matching different types, styles, developers, plugins, etc. OpenLogic Company Confidential 12 Wednesday, July 29, 2009
  • Automatic Generation-Based Caching Generation-based Partition the cache so that every state change increments the “generation” Automatic Any action that could possibly change state bumps the count Let memcached overwrite old generations Very conservative No domain knowledge Don’t cache errors, AJAX, redirects, flash notices, etc. OpenLogic Company Confidential 13 Wednesday, July 29, 2009
  • Overview Non-cached Cached Rails Rails plumbing plumbing Your Cache code helper Render Database memcached View OpenLogic Company Confidential 14 Wednesday, July 29, 2009
  • Cache = Hash Key Value /packages/1 <html><body>Rails</body></html> /packages/2 <html><body>Ruby</body></html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Generational Cache Key Value /gen/1/packages/1 <html>Rails</html> /gen/1/packages/2 <html>Ruby</html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Generational Cache Key Value /gen/1/packages/1 <html>Rails</html> /gen/1/packages/2 <html>Ruby</html> /gen/2/packages/1 <html>Ruby on Rails</html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • memcached is your friend Very fast Don’t worry about removing old entries memcached will automatically drop the oldest keys when it runs low on memory Run it on your web servers if you have the RAM OpenLogic Company Confidential 18 Wednesday, July 29, 2009
  • Cache Helper No cache-related code sprinkled throughout every model, view, and/or controller Use a global “around” filter Automatically increment (scoped) generation count upon POST, PUT, or DELETE Handle event recording and playback (optional) OpenLogic Company Confidential 19 Wednesday, July 29, 2009
  • Cache Helper Code (in “around” filter) key = make_auto_cache_key(request.request_uri) output = Rails.cache.read(key) if output render :text => output return else yield unless response.redirected_to || flash[:notice] Rails.cache.write(key, response.body) end end OpenLogic Company Confidential 20 Wednesday, July 29, 2009
  • Cache Key def make_auto_cache_key(key) ol_gen = Rails.cache.fetch(OL_GEN) { "1" } "olex/#{ol_gen}" end OpenLogic Company Confidential 21 Wednesday, July 29, 2009
  • “Clear” the Cache POST, PUT, or DELETE “clears” the cache def maybe_clear_auto_cache return if request.get? gen = Rails.cache.fetch(OL_GEN) { "1" } Rails.cache.write(OL_GEN, (gen.to_i + 1).to_s) end OpenLogic Company Confidential 22 Wednesday, July 29, 2009
  • Controller Customization Some controllers may need special cache control (e.g., user-specific cache, disable cache for certain methods) olex_auto_cache_is_specific_to_user :only => :show Note: the cache may still need to be cleared when skipping cache usage! skip_filter :olex_auto_cache after_filter :maybe_clear_olex_auto_cache OpenLogic Company Confidential 23 Wednesday, July 29, 2009
  • Cache Partitioning Make it impossible for users of different corporations and permission levels to see each other’s stuff, access the same cache, clear somebody else’s cache, etc. Make sure any “global” changes clear all caches Use a cache hierarchy /olex/<gen #>/corp/<corp #>/<corp gen #>/roles/<role #s>/URL MD5 the key (memcached has a 250 char limit) Extra credit: Use the key as an etag OpenLogic Company Confidential 24 Wednesday, July 29, 2009
  • Partitioned Cache Global generation <html> /olex/13/corp/72/2/roles/2,7,19/packages/2 Rails (unsupported) </html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Partitioned Cache Corporate account ID <html> /olex/13/corp/72/2/roles/2,7,19/packages/2 Rails (unsupported) </html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Partitioned Cache Corporation #72’s generation <html> /olex/13/corp/72/2/roles/2,7,19/packages/2 Rails (unsupported) </html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Partitioned Cache Current user’s role IDs <html> /olex/13/corp/72/2/roles/2,7,19/packages/2 Rails (unsupported) </html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Partitioned Cache URL <html> /olex/13/corp/72/2/roles/2,7,19/packages/2 Rails (unsupported) </html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Partitioned Cache <html> /olex/13/corp/72/2/roles/2,7,19/packages/2 Rails (unsupported) </html> <html> /olex/13/corp/72/2/roles/2,7,19,22/packages/2 Rails (manager secret!) </html> <html> /olex/14/corp/72/2/roles/2,7,19/packages/2 Rails (supported) </html> /olex/14/guest/packages/2 <html>Rails</html> OpenLogic Company Confidential Wednesday, July 29, 2009
  • Cache Key def make_auto_cache_key(key, user = nil) ol_gen = Rails.cache.fetch(OL_GEN) { "1" } ol_prefix = "olex/#{ol_gen}" if user.nil? && self.respond_to?("current_user") user = current_user end ca = get_corporate_account(user) ... OpenLogic Company Confidential 31 Wednesday, July 29, 2009
  • Cache Key ... if user.is_corp_user? corp_gen = Rails.cache.fetch(corp_gen_key(ca)){"1"} final_key = make_corp_key(user, ca, key, corp_gen) else final_key = "guest#{key}" end OpenLogic Company Confidential 32 Wednesday, July 29, 2009
  • Corporate Cache Key def make_corp_key(user, ca, key, corp_gen) roles = role_string(user) "/corp/#{ca.id}/#{corp_gen}/roles/#{roles}#{key}" end def role_string(user) Rails.cache.fetch("roles/#{user.id}") do user.role_string end end OpenLogic Company Confidential 33 Wednesday, July 29, 2009
  • Benefits Never have to explicitly expire anything Can’t get an expired page Generation numbers also stored in memcached Cache hierarchy is like a directory structure Easy to grok Can’t run out of “disk space”! OpenLogic Company Confidential 34 Wednesday, July 29, 2009
  • Does it really work? In production for over a year - a few minor issues See Gotchas Huge performance improvement for us, almost no developer pain e.g., needed cookie-based “Welcome Joe!” Great for “passive” caching Write caching code once, enjoy it forever Lots of room for more aggressive caching OpenLogic Company Confidential 35 Wednesday, July 29, 2009
  • Gotchas Easy to forget to make AJAX calls use REST method:'get','post', 'put', or 'delete' Test with and without caching, and test the caching itself! Caching doesn’t help the first hit Mitigate by pre-caching when feasible OpenLogic Company Confidential 36 Wednesday, July 29, 2009
  • Recommendations The “safety first” caching implementation - use it It’s still action caching, so don’t expect page caching performance Measure the result - not all pages will benefit and there is some overhead OpenLogic Company Confidential 37 Wednesday, July 29, 2009
  • Bonus Asynchronous pre-caching Event recording and playback OpenLogic Company Confidential 38 Wednesday, July 29, 2009
  • Async pre-caching pages at logon Use Workling/Starling for async When user logs on, make async call Async call runs through list of URL’s and hits them on behalf of the currently logged on user Need secret back-door logon in application.rb Use big scary session key in environment.rb OpenLogic Company Confidential 39 Wednesday, July 29, 2009
  • Event Recording Q: What if you want to record the fact that something happened even though the page was automatically cached and served? A: Watch it while being cached, record what happens in memcached, play it back later when serving cached version OpenLogic Company Confidential 40 Wednesday, July 29, 2009
  • Summary Rails built-in caching takes a lot of on-going work Easy to screw it up Automatic caching can be written once and enjoyed forever Much harder to screw up Still possible to use more aggressive techniques selectively OpenLogic Company Confidential 41 Wednesday, July 29, 2009
  • Any questions for Rod? OpenLogic Company Confidential 42 Wednesday, July 29, 2009
  • Resources memcached: http://www.danga.com/memcached/ Workling: http://github.com/purzelrakete/workling/tree/ master Starling: http://rubyforge.org/projects/starling/ OLEX: http://olex.openlogic.com OpenLogic Company Confidential 43 Wednesday, July 29, 2009
  • Credits Unless otherwise indicated, photos were licensed from BigStockPhoto.com OpenLogic Company Confidential 44 Wednesday, July 29, 2009
  • OpenLogic is hiring! Rails guru? Live near Denver, Colorado? Love Open Source? Come see me! OpenLogic Company Confidential 45 Wednesday, July 29, 2009