Page Caching Resurrected

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Notes on slide 1






    super simple to use, but results in PUBLIC content

    super simple to use, but results in PUBLIC content





    more framework-specific; solves auth-protected pages, etc. - cached content is not publicly available

    more framework-specific; solves auth-protected pages, etc. - cached content is not publicly available





    caches only specific parts of the page, which are not publically available

    expiration of each fragment, individually



    10 minutes









    15 minutes













    22 minutes








    26 minutes







    135ms for hybrid, which is 21% of the standard

    lame tests I employed showed the same or greater effect

    26 minutes




    66ms for hybrid v2, 10.6% of standard and 48% of hybrid

    34 minutes










    5 Favorites & 1 Group

    Page Caching Resurrected - Presentation Transcript

    1. Page Caching Resurrected Ben Sco eld – Viget Labs
    2. Page Caching Resurrected: A Fairy Tale Ben Sco eld – Viget Labs
    3. three little pigs
    4. three little pigs
    5. page caching
    6. 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
    7. 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
    8. 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
    9. standard 1 page 3000 requests per second
    10. public dynamic content
    11. action caching
    12. 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
    13. 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
    14. 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
    15. standard 1 action 500 page 3000 requests per second
    16. dynamic content
    17. fragment caching
    18. <% cache(:key => 'index:piglist') do %> <ul id=\"pig-list\"> <% @pigs.each do |pig| %> <li> <%= image_tag pig.house.photo %> <%= h pig.name %> </li> <% end %> </ul> <% end %>
    19. <% cache(:key => 'index:piglist') do %> <ul id=\"pig-list\"> <% @pigs.each do |pig| %> <li> <%= image_tag pig.house.photo %> <%= h pig.name %> </li> <% end %> </ul> <% end %>
    20. class PigsController # ... def update @pig = Pig.find(params[:id]) @pig.update_attributes(params[:pig]) expire_fragment :key => 'index:piglist' end end
    21. class PigsController # ... def update @pig = Pig.find(params[:id]) @pig.update_attributes(params[:pig]) expire_fragment :key => 'index:piglist' end end
    22. standard 1 fragment 20 action 500 page 3000 requests per second
    23. eficiency
    24. the idea
    25. Rails 2.3
    26. hello, metal
    27. class BigBadWolf def self.call(env) if env[\"PATH_INFO\"] =~ /^\\/threaten/ [ 200, {\"Content-Type\" => \"text/html\"}, \"Little pig, little pig, let me in!\" ] else [ 404, {\"Content-Type\" => \"text/html\"}, \"Not Found\" ] end end end
    28. high-performance endpoints
    29. AJAX
    30. so...
    31. javascript
    32. <ul id=\"logged-out-nav\" class=\"usernav\" style=\"display:none\"> <li class=\"first sign-out-link\"> <a class=\"utility-link\" href=\"#\" id=\"login-link\" onclick=\"Login.show($('top-login-form')); return false;\">Login</a> </li> <li class=\"signin-border-left\"> <a href=\"/users/forgot_password\" class=\"utility-link\">Forgot Password?</a> </li> <li class=\"signin-border-left\"> <a href=\"/signup\" class=\"utility-link\">Sign Up</a> </li> </ul>
    33. <div id=\"top-login-form\" class=\"usernav login-form\" style=\"display:none\"> <form action=\"https://secure.hulu.com/account/authenticate\" method=\"get\" name=\"login-form\" onsubmit=\"Login.submit(this); return false;\"> <span class=\"login-status\"></span> <input id=\"login\" class=\"active login\" type=\"text\" style=\"display: none;\" name=\"username\"/> <input id=\"password\" class=\"active password\" type=\"password\" style=\"display: none;\" name=\"password\"/> <input class=\"inactive dummy login\" type=\"text\" value=\"username\" name=\"dummy_login\" /> <input class=\"inactive dummy\" type=\"text\" value=\"password\" name=\"dummy_password\" /> <input alt=\"Login\" class=\"login-submit\" src=\"http://static.hulu.com/images/btn-signin-small.gif?1237361096\" style=\"width: 39px; height: 20;\" type=\"image\" /> <a href=\"#\"><img alt=\"Cancel\" border=\"0\" class=\"hover-me\" height=\"20\" id=\"btn-x.gif123741536309506\" onclick=\"Login.cancel();return false\" src=\"http://static.hulu.com/images/btn-x.gif?1237361096\" width=\"18\" /></a> </form> <a href=\"/signup\" class=\"utility-link\">Sign Up</a> </div>
    34. <ul id=\"logged-in-nav\" class=\"usernav\" style=\"display:none\"> <li id=\"welcome-username\" class=\"first\"> Welcome </li> <li> <a href=\"/profile\" class=\"utility-link\">Profile</a> </li> <li> <a href=\"/profile/queue\" class=\"utility-link\" id=\"your-queue-link\">Queue</a> </li> <li class=\"sign-out-link\"> <a href=\"#\" id=\"top-nav-sign-out\" onclick=\"new Ajax.Request(...)\">Sign Out</a> </li> </ul>
    35. <noscript> <ul class=\"nojs usernav\"> <li> Please <a href=\"/support/\">enable javascript</a> to log in. </li> </ul> </noscript>
    36. <script type=\"text/javascript\" charset=\"utf-8\">/*<![CDATA[*/ Event.observe(window, \"load\", function() { Behaviors.onLoad(); Behaviors.setLoggedIn(); Login.setup(); if ($(\"login\") && $(\"login-form\")) { 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 = \"https://secure.hulu.com/account/authenticate\" + '?' + ... el.appendChild(script); } } /*]]>*/</script>
    37. <ul id=\"logged-in-nav\" class=\"usernav\" style=\"display:none\"> <li id=\"welcome-username\" class=\"first\"> Welcome </li> <li> <a href=\"/profile\" class=\"utility-link\">Profile</a> </li> <li> <a href=\"/profile/queue\" class=\"utility-link\" id=\"your-queue-link\">Queue</a> </li> <li class=\"sign-out-link\"> <a href=\"#\" id=\"top-nav-sign-out\" onclick=\"new Ajax.Request(...)\">Sign Out</a> </li> </ul>
    38. <ul id=\"logged-in-nav\" class=\"usernav\" style=\"display:none\"> <li id=\"welcome-username\" class=\"first\"> Welcome </li> <li> <a href=\"/profile\" class=\"utility-link\">Profile</a> </li> <li> <a href=\"/profile/queue\" class=\"utility-link\" id=\"your-queue-link\">Queue</a> </li> <li class=\"sign-out-link\"> <a href=\"#\" id=\"top-nav-sign-out\" onclick=\"new Ajax.Request(...)\">Sign Out</a> </li> </ul>
    39. hulu is insane don’t do it like they do
    40. <script type=\"text/javascript\" charset=\"utf-8\">/*<![CDATA[*/ Event.observe(window, \"load\", function() { Behaviors.onLoad(); Behaviors.setLoggedIn(); Login.setup(); if ($(\"login\") && $(\"login-form\")) { 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 = \"https://secure.hulu.com/account/authenticate\" + '?' + ... el.appendChild(script); } } /*]]>*/</script>
    41. <script type=\"text/javascript\" charset=\"utf-8\">/*<![CDATA[*/ Event.observe(window, \"load\", function() { Behaviors.onLoad(); Behaviors.setLoggedIn(); Login.setup(); if ($(\"login\") && $(\"login-form\")) { 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 = \"https://secure.hulu.com/account/authenticate\" + '?' + ... el.appendChild(script); } } /*]]>*/</script>
    42. the* right way *a
    43. the standard approach
    44. class ItemsController < ApplicationController def index @user = User.find_by_login(params[:user]) @items = Item.released_on(params[:date]) end end
    45. 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
    46. <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>
    47. the hybrid approach
    48. class ItemsController < ApplicationController caches_page :index def index @items = Item.released_on(params[:date]).all end end
    49. require(File.dirname(__FILE__) + \"/../../config/environment\") unless defined?(Rails) class PullList def self.call(env) if env[\"PATH_INFO\"] =~ /^\\/pulls/ date = '2008-11-05' user = '1' [ 200, {\"Content-Type\" => \"application/javascript\"}, [Pull.by_user(user).for_date(date).map {|i| i.item_id}.to_json]] else [404, {\"Content-Type\" => \"text/html\"}, [\"Not Found\"]] end end end
    50. 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
    51. $(document).ready(function() { $.getJSON('/pulls', function(data) { $.each(data, function() { $('#item_'+this).addClass('pulled'); }); }); });
    52. standard
    53. hybrid
    54. standard 0.617 hybrid 0.039 0.096 content load time
    55. hybrid approach - version 2
    56. class SessionsController < ApplicationController def new; end def create # ... session[:pulls] = @user.pulls.map {|i| i.item_id} redirect_to items_path end end
    57. require(File.dirname(__FILE__) + \"/../../config/environment\") unless defined?(Rails) class PullList def self.call(env) if env[\"PATH_INFO\"] =~ /^\\/pulls/ date = '2008-11-05' user = '1' [ 200, {\"Content-Type\" => \"application/javascript\"}, [env['rack.session'][:pulls].to_json] ] else [404, {\"Content-Type\" => \"text/html\"}, [\"Not Found\"]] end end end
    58. hybrid v2
    59. standard 0.617 hybrid 0.039 0.096 hybrid v2 0.043 0.023 content load time
    60. when to use it
    61. when not to use it
    62. accessibility
    63. accessibility
    64. <noscript> <ul class=\"nojs usernav\"> <li> Please <a href=\"/support/\">enable javascript</a> to log in. </li> </ul> </noscript>
    65. Thank You ben sco eld - @bsco eld - http://www.viget.com/extend - http://www.speakerrate.com/bsco eld

    + Ben ScofieldBen Scofield, 7 months ago

    custom

    1755 views, 5 favs, 0 embeds more stats

    This is the revised version of my Page Caching Resu more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 1755
      • 1755 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 5
    • Downloads 38
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories

    Groups / Events