Page Caching Resurrected: A Fairy Tale
Upcoming SlideShare
Loading in...5
×
 

Page Caching Resurrected: A Fairy Tale

on

  • 1,873 views

Presentation given at the first Developer Day, in Durham NC on March 21st, 2009

Presentation given at the first Developer Day, in Durham NC on March 21st, 2009

Statistics

Views

Total Views
1,873
Views on SlideShare
1,871
Embed Views
2

Actions

Likes
3
Downloads
13
Comments
0

1 Embed 2

http://www.slideshare.net 2

Accessibility

Upload Details

Uploaded via as Apple Keynote

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
  • <br />
  • <br />
  • <br />
  • <br />
  • 3 minutes <br />
  • <br />
  • <br />
  • <br />
  • super simple to use, but results in PUBLIC content <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • more framework-specific; solves auth-protected pages, etc. - cached content is not publicly available <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • caches only specific parts of the page, which are not publically available <br />
  • expiration of each fragment, individually <br />
  • <br />
  • <br />
  • 10 minutes <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • 15 minutes <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • 22 minutes <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • 26 minutes <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • 32 minutes <br />
  • <br />
  • <br />
  • <br />
  • 135ms for hybrid, which is 21% of the standard <br /> <br /> lame tests I employed showed the same or greater effect <br />
  • 34 minutes <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

Page Caching Resurrected: A Fairy Tale Page Caching Resurrected: A Fairy Tale Presentation Transcript

  • Page Caching Resurrected: Ben Sco eld – Viget Labs Sunday, March 22, 2009
  • Page Caching Resurrected: A Fairy Tale Ben Sco eld – Viget Labs Sunday, March 22, 2009
  • I’m a Rails guy Sunday, March 22, 2009
  • and this is a Rails talk Sunday, March 22, 2009
  • but this isn’t just for Rails Sunday, March 22, 2009
  • the story Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • page caching Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • class PigsController caches_page :show def show @pig = Pig.find(params[:id]) end def update @pig = Pig.find(params[:id]) @pig.update_attributes(params[:pig]) expire_page :action => :show end end Sunday, March 22, 2009
  • Standard 1 Page 3000 requests per second Sunday, March 22, 2009
  • public dynamic content Sunday, March 22, 2009
  • action caching Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • class PigsController require_login :show caches_action :show def show @pig = Pig.find(params[:id]) end def update @pig = Pig.find(params[:id]) @pig.update_attributes(params[:pig]) expire_action :action => :show end end Sunday, March 22, 2009
  • Standard 1 Action 500 Page 3000 requests per second Sunday, March 22, 2009
  • dynamic content Sunday, March 22, 2009
  • fragment caching Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • <% cache(:key => 'index:piglist') do %> <ul id=quot;pig-listquot;> <% @pigs.each do |pig| %> <li> <%= image_tag pig.house.photo %> <%= h pig.name %> </li> <% end %> </ul> <% end %> Sunday, March 22, 2009
  • class PigsController # ... def update @pig = Pig.find(params[:id]) @pig.update_attributes(params[:pig]) expire_fragment :key => 'index:piglist' end end Sunday, March 22, 2009
  • Standard 1 Fragment 20 Action 500 Page 3000 requests per second Sunday, March 22, 2009
  • efficiency Sunday, March 22, 2009
  • the idea Sunday, March 22, 2009
  • Rails 2.3 Sunday, March 22, 2009
  • hello, metal Sunday, March 22, 2009
  • class BigBadWolf def self.call(env) if env[quot;PATH_INFOquot;] =~ /^/threaten/ [ 200, {quot;Content-Typequot; => quot;text/htmlquot;}, quot;Little pig, little pig, let me in!quot; ] else [ 404, {quot;Content-Typequot; => quot;text/htmlquot;}, quot;Not Foundquot; ] end end end Sunday, March 22, 2009
  • high-performance endpoints Sunday, March 22, 2009
  • AJAX Sunday, March 22, 2009
  • so... Sunday, March 22, 2009
  • javascript Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • <script type=quot;text/javascriptquot; charset=quot;utf-8quot;>/*<![CDATA[*/ Event.observe(window, quot;loadquot;, function() { Behaviors.onLoad(); Behaviors.setLoggedIn(); Login.setup(); if ($(quot;loginquot;) && $(quot;login-formquot;)) { Event.observe('login', 'keydown', function(ev) { if (ev.keyCode == 13) { Login.submit(); } }); } }); Login.auth = function(login, password) { document.cookie = 'login=' + login + '; path=/account/authenticate; secure; ... document.cookie = 'password=' + password + '; path=/account/authenticate; ... el = $$('body').first(); if (el) { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = quot;https://secure.hulu.com/account/authenticatequot; + '?' + ... el.appendChild(script); } } /*]]>*/</script> Sunday, March 22, 2009
  • <ul id=quot;logged-in-navquot; class=quot;usernavquot; style=quot;display:nonequot;> <li id=quot;welcome-usernamequot; class=quot;firstquot;> Welcome </li> <li> <a href=quot;/profilequot; class=quot;utility-linkquot;>Profile</a> </li> <li> <a href=quot;/profile/queuequot; class=quot;utility-linkquot; id=quot;your-queue-linkquot;>Queue</a> </li> <li class=quot;sign-out-linkquot;> <a href=quot;#quot; id=quot;top-nav-sign-outquot; onclick=quot;new Ajax.Request(...)quot;>Sign Out</a> </li> </ul> <ul id=quot;logged-out-navquot; class=quot;usernavquot; style=quot;display:nonequot;> <li class=quot;first sign-out-linkquot;> <a class=quot;utility-linkquot; href=quot;#quot; id=quot;login-linkquot; onclick=quot;Login.show($('top-login-form')); return false;quot;>Login</a> </li> <li class=quot;signin-border-leftquot;> <a href=quot;/users/forgot_passwordquot; class=quot;utility-linkquot;>Forgot Password?</a> </li> <li class=quot;signin-border-leftquot;> <a href=quot;/signupquot; class=quot;utility-linkquot;>Sign Up</a> </li> </ul> Sunday, March 22, 2009
  • <noscript> <ul class=quot;nojs usernavquot;> <li> Please <a href=quot;/support/quot;>enable javascript</a> to log in. </li> </ul> </noscript> <div id=quot;top-login-formquot; class=quot;usernav login-formquot; style=quot;display:nonequot;> <form action=quot;https://secure.hulu.com/account/authenticatequot; method=quot;getquot; name=quot;login-formquot; onsubmit=quot;Login.submit(this); return false;quot;> <span class=quot;login-statusquot;></span> <input id=quot;loginquot; class=quot;active loginquot; type=quot;textquot; style=quot;display: none;quot; name=quot;usernamequot;/> <input id=quot;passwordquot; class=quot;active passwordquot; type=quot;passwordquot; style=quot;display: none;quot; name=quot;passwordquot;/> <input class=quot;inactive dummy loginquot; type=quot;textquot; value=quot;usernamequot; name=quot;dummy_loginquot; /> <input class=quot;inactive dummyquot; type=quot;textquot; value=quot;passwordquot; name=quot;dummy_passwordquot; /> <input alt=quot;Loginquot; class=quot;login-submitquot; src=quot;http://static.hulu.com/images/btn-signin-small.gif?1237361096quot; style=quot;width: 39px; height: 20;quot; type=quot;imagequot; /> <a href=quot;#quot;><img alt=quot;Cancelquot; border=quot;0quot; class=quot;hover-mequot; height=quot;20quot; id=quot;btn-x.gif123741536309506quot; onclick=quot;Login.cancel();return falsequot; src=quot;http://static.hulu.com/images/btn-x.gif?1237361096quot; width=quot;18quot; /></a> </form> <a href=quot;/signupquot; class=quot;utility-linkquot;>Sign Up</a> </div> Sunday, March 22, 2009
  • <ul id=quot;logged-in-navquot; class=quot;usernavquot; style=quot;display:nonequot;> <li id=quot;welcome-usernamequot; class=quot;firstquot;> Welcome </li> <li> <a href=quot;/profilequot; class=quot;utility-linkquot;>Profile</a> </li> <li> <a href=quot;/profile/queuequot; class=quot;utility-linkquot; id=quot;your-queue-linkquot;>Queue</a> </li> <li class=quot;sign-out-linkquot;> <a href=quot;#quot; id=quot;top-nav-sign-outquot; onclick=quot;new Ajax.Request(...)quot;>Sign Out</a> </li> </ul> <ul id=quot;logged-out-navquot; class=quot;usernavquot; style=quot;display:nonequot;> <li class=quot;first sign-out-linkquot;> <a class=quot;utility-linkquot; href=quot;#quot; id=quot;login-linkquot; onclick=quot;Login.show($('top-login-form')); return false;quot;>Login</a> </li> <li class=quot;signin-border-leftquot;> <a href=quot;/users/forgot_passwordquot; class=quot;utility-linkquot;>Forgot Password?</a> </li> <li class=quot;signin-border-leftquot;> <a href=quot;/signupquot; class=quot;utility-linkquot;>Sign Up</a> </li> </ul> Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • hulu is insane don’t do it like they do Sunday, March 22, 2009
  • <script type=quot;text/javascriptquot; charset=quot;utf-8quot;>/*<![CDATA[*/ Event.observe(window, quot;loadquot;, function() { Behaviors.onLoad(); Behaviors.setLoggedIn(); Login.setup(); if ($(quot;loginquot;) && $(quot;login-formquot;)) { Event.observe('login', 'keydown', function(ev) { if (ev.keyCode == 13) { Login.submit(); } }); } }); Login.auth = function(login, password) { document.cookie = 'login=' + login + '; path=/account/authenticate; secure; ... document.cookie = 'password=' + password + '; path=/account/authenticate; ... el = $$('body').first(); if (el) { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = quot;https://secure.hulu.com/account/authenticatequot; + '?' + ... el.appendChild(script); } } /*]]>*/</script> Sunday, March 22, 2009
  • <script type=quot;text/javascriptquot; charset=quot;utf-8quot;>/*<![CDATA[*/ Event.observe(window, quot;loadquot;, function() { Behaviors.onLoad(); Behaviors.setLoggedIn(); Login.setup(); if ($(quot;loginquot;) && $(quot;login-formquot;)) { Event.observe('login', 'keydown', function(ev) { if (ev.keyCode == 13) { Login.submit(); } }); } }); Login.auth = function(login, password) { document.cookie = 'login=' + login + '; path=/account/authenticate; secure; ... document.cookie = 'password=' + password + '; path=/account/authenticate; ... el = $$('body').first(); if (el) { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = quot;https://secure.hulu.com/account/authenticatequot; + '?' + ... el.appendChild(script); } } /*]]>*/</script> Sunday, March 22, 2009
  • the* right way *a Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • the standard approach Sunday, March 22, 2009
  • class ItemsController < ApplicationController def index @user = User.find_by_login(params[:user]) @items = Item.released_on(params[:date]) end end Sunday, March 22, 2009
  • class Item < ActiveRecord::Base has_many :pulls, :dependent => :destroy named_scope :released_on, lambda { |date| date ||= Item.maximum(:released_on) {:conditions => {:released_on => date}, :order => 'name ASC'} } def pulled_by?(user) x = user.nil? ? false : !self.pulls.by_user(user.id).empty? end end Sunday, March 22, 2009
  • <h1>Releases</h1> <ul> <% @items.each do |item| %> <% content_tag_for :li, item do %> <%= image_tag 'cover.png', :alt => h(item.name), :class => 'cover' %> <%= image_tag('badge.png', :alt => 'pulling',:class => 'badge') if item.pulled_by?(@user) %> <p><%= h item.name %></p> <% end %> <% end %> </ul> Sunday, March 22, 2009
  • the hybrid approach Sunday, March 22, 2009
  • class ItemsController < ApplicationController caches_page :index def index @items = Item.released_on(params[:date]).all end end Sunday, March 22, 2009
  • require(File.dirname(__FILE__) + quot;/../../config/environmentquot;) unless defined?(Rails) class PullList def self.call(env) if env[quot;PATH_INFOquot;] =~ /^/pulls/ date = '2008-11-05' user = '1' [ 200, {quot;Content-Typequot; => quot;application/javascriptquot;}, [Pull.by_user(user).for_date(date).map {|i| i.item_id}.to_json]] else [404, {quot;Content-Typequot; => quot;text/htmlquot;}, [quot;Not Foundquot;]] end end end Sunday, March 22, 2009
  • class Pull < ActiveRecord::Base belongs_to :user belongs_to :item named_scope :by_user, lambda { |user_id| {:conditions => {:user_id => user_id}} } named_scope :for_date, lambda { |date| {:include => :item, :conditions => {:items => {:released_on => date}}} } end Sunday, March 22, 2009
  • $(document).ready(function() { $.getJSON('/pulls', function(data) { $.each(data, function() { $('#item_'+this).addClass('pulled'); }); }); }); Sunday, March 22, 2009
  • the payoff Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • standard Sunday, March 22, 2009
  • hybrid Sunday, March 22, 2009
  • Standard 0.617 Hybrid 0.039 0.096 content load time Sunday, March 22, 2009
  • when to use it Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • Sunday, March 22, 2009
  • no shirt, no javascript, no service Sunday, March 22, 2009
  • Thank You ben sco eld - @bsco eld - http://www.viget.com/extend - http://www.speakerrate.com/speakers/44 Sunday, March 22, 2009