ݺߣ

ݺߣShare a Scribd company logo
Caching tips




     Leo Soto M.
     Continuum
     Lecture & Beef, Marzo 2013

Sunday, March 3, 13
Caching tips
     (for webapps)




     Leo Soto M.
     Continuum
     Lecture & Beef, Marzoss 2013

Sunday, March 3, 13
“There are only
      two hard things
      in computer
      science...



Sunday, March 3, 13
...cache
                      invalidation and
                      naming things”

                      - Phil Karlton


Sunday, March 3, 13
HTTP Caching

                      •Client-side!
                      •...or “middle-side” (proxys!)
                      •Conceptos claves:
                       •Frescura (freshness)
                       •Validacion/Invalidacion

Sunday, March 3, 13
FRESH CACHES


                •HTTP/1.0:
                      Expires:	
  Fri,	
  01	
  March	
  2013	
  20:00:00	
  GMT

                •HTTP/1.1:
                      Cache-­‐Control:	
  *pila-­‐de-­‐opciones*
                      Cache-­‐Control:	
  private,	
  max-­‐age=3600




Sunday, March 3, 13
VALIDATED CACHES

                •HTTP/1.0:
                      Last-­‐Modified	
  /	
  If-­‐Modified-­‐Since
                      304	
  Not	
  Modified

                •HTTP/1.1:
                      ETag	
  /	
  If-­‐None-­‐Match
                      304	
  Not	
  Modified




Sunday, March 3, 13
CACHE INVALIDATION

                •METODOS HTTP QUE INVALIDAN
                      CACHES FRESCAS:
                      POST	
  /resource
                      DELETE	
  /resource
                      PUT	
  /resource




Sunday, March 3, 13
EN RAILS

                •FRESH CACHES:
                      expires_in	
  1.hour



                •VALIDATED CACHES
                      if	
  stale?(etag:	
  @modelo)
                      	
  	
  otros_hits_a_la_bd
                      end

Sunday, March 3, 13
stale?(etag:	
  x)	
  -­‐>	
  Etag:	
  md5(expand_cache_key(x))
     # File activesupport/lib/active_support/cache.rb, line 77
     def expand_cache_key(key, namespace = nil)
       expanded_cache_key = namespace ? "#{namespace}/" : ""

          if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
            expanded_cache_key << "#{prefix}/"
          end

       expanded_cache_key << retrieve_cache_key(key)
       expanded_cache_key
     end

   # File activesupport/lib/active_support/cache.rb, line 90
   def retrieve_cache_key(key)
     case
     when key.respond_to?(:cache_key) then key.cache_key
     when key.is_a?(Array)            then key.map { |element|
       retrieve_cache_key(element)
     }.to_param
     else
     end.to_s
   end

Sunday, March 3, 13
# File activerecord/lib/active_record/integration.rb, line 37
    def cache_key
      case
      when new_record?
        "#{self.class.model_name.cache_key}/new"
      when timestamp = self[:updated_at]
        timestamp = timestamp.utc.to_s(:number)
        "#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
      else
        "#{self.class.model_name.cache_key}/#{id}"
      end
    end




Sunday, March 3, 13
EN RAILS



                •SIN ETAGGER
                      stale?(etag:	
  [current_user,	
  @modelo])
                      stale?(etag:	
  [current_user,	
  @otro])
                      stale?(etag:	
  [current_user,	
  @otromas])




Sunday, March 3, 13
EN RAILS


                •CON ETAGGER
                      etag	
  {	
  current_user	
  }
                      stale?(etag:	
  modelo)
                      stale?(etag:	
  otro)
                      stale?(etag:	
  otromas)



Sunday, March 3, 13
EN RAILS


                •EN AC PERFORACIONES
                      etag	
  {	
  [current_user,	
  ENV[‘COMMIT_HASH’]	
  }
                      stale?(etag:	
  modelo)
                      stale?(etag:	
  otro)
                      stale?(etag:	
  otromas)



Sunday, March 3, 13
Rails Fragment
                         Caching
                      -­‐cache	
  ‘foo’	
  do...end
                      -­‐cache	
  modelo	
  do...end
                      -­‐cache	
  [reporte,	
  ‘inbox’]	
  do..end


   # File actionpack/lib/action_controller/caching/fragments.rb, line 51
   def fragment_cache_key(key)
     ActiveSupport::Cache.expand_cache_key(
       key.is_a?(Hash) ?
         url_for(key).split("://").last :
         key,
     :views)
   end

Sunday, March 3, 13
RUSSIAN DOLL
                                 CACHING

                      -­‐	
  cache	
  [reporte,	
  ‘perforaciones’]	
  do
                      	
  	
  -­‐	
  perforacion.each	
  do	
  |p|
                      	
  	
  	
  	
  -­‐	
  cache	
  perforacion	
  do
                      	
  	
  	
  	
  	
  	
  %h1=	
  perforacion.titulo
                      	
  	
  	
  	
  	
  	
  %p=	
  perforacion.whatever




Sunday, March 3, 13
TIPS FRAGMENT
                           CACHING


                •Aplicar a cosas que no
                      dependan del usuario actual
                •Usar cache_digests +
                      memcached




Sunday, March 3, 13
CONCLUSIONES
                •HTTP CACHING:
                 •CACHE LOCAL AL USUARIO
                 •AHORRA:
                  •LATENCIA
                  •ANCHO DE BANDA,
                  •TIEMPO DE RESPUESTA DEL
                       SERVIDOR

Sunday, March 3, 13
CONCLUSIONES
                •FRAGMENT CACHING:
                 •CACHE GLOBAL DE LA APP
                 •AHORRA:
                  •HITS A LA BD
                  •CALCULOS
                  •RENDERING
Sunday, March 3, 13
BONUS TRACK
    def prefetch(url)
      content_tag("script",
        %Q{
        $("<link href='#{escape_javascript(url)}'
                 rel='subresource'/>").appendTo('head')
        }.html_safe
      ) unless current_page?(url)
    end


    def tab_detalle_reporte(text, opts = {})
       collection = opts[:collection] || text.downcase.pluralize
       url = send("reporte_#{collection}_path", estado, reporte)
       tab_title(opts.merge!(
         name: text,
         href: url,
         active: tab == collection
       )) + prefetch(url)
     end

Sunday, March 3, 13

More Related Content

Caching tips

  • 1. Caching tips Leo Soto M. Continuum Lecture & Beef, Marzo 2013 Sunday, March 3, 13
  • 2. Caching tips (for webapps) Leo Soto M. Continuum Lecture & Beef, Marzoss 2013 Sunday, March 3, 13
  • 3. “There are only two hard things in computer science... Sunday, March 3, 13
  • 4. ...cache invalidation and naming things” - Phil Karlton Sunday, March 3, 13
  • 5. HTTP Caching •Client-side! •...or “middle-side” (proxys!) •Conceptos claves: •Frescura (freshness) •Validacion/Invalidacion Sunday, March 3, 13
  • 6. FRESH CACHES •HTTP/1.0: Expires:  Fri,  01  March  2013  20:00:00  GMT •HTTP/1.1: Cache-­‐Control:  *pila-­‐de-­‐opciones* Cache-­‐Control:  private,  max-­‐age=3600 Sunday, March 3, 13
  • 7. VALIDATED CACHES •HTTP/1.0: Last-­‐Modified  /  If-­‐Modified-­‐Since 304  Not  Modified •HTTP/1.1: ETag  /  If-­‐None-­‐Match 304  Not  Modified Sunday, March 3, 13
  • 8. CACHE INVALIDATION •METODOS HTTP QUE INVALIDAN CACHES FRESCAS: POST  /resource DELETE  /resource PUT  /resource Sunday, March 3, 13
  • 9. EN RAILS •FRESH CACHES: expires_in  1.hour •VALIDATED CACHES if  stale?(etag:  @modelo)    otros_hits_a_la_bd end Sunday, March 3, 13
  • 10. stale?(etag:  x)  -­‐>  Etag:  md5(expand_cache_key(x)) # File activesupport/lib/active_support/cache.rb, line 77 def expand_cache_key(key, namespace = nil) expanded_cache_key = namespace ? "#{namespace}/" : "" if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"] expanded_cache_key << "#{prefix}/" end expanded_cache_key << retrieve_cache_key(key) expanded_cache_key end # File activesupport/lib/active_support/cache.rb, line 90 def retrieve_cache_key(key) case when key.respond_to?(:cache_key) then key.cache_key when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param else end.to_s end Sunday, March 3, 13
  • 11. # File activerecord/lib/active_record/integration.rb, line 37 def cache_key case when new_record? "#{self.class.model_name.cache_key}/new" when timestamp = self[:updated_at] timestamp = timestamp.utc.to_s(:number) "#{self.class.model_name.cache_key}/#{id}-#{timestamp}" else "#{self.class.model_name.cache_key}/#{id}" end end Sunday, March 3, 13
  • 12. EN RAILS •SIN ETAGGER stale?(etag:  [current_user,  @modelo]) stale?(etag:  [current_user,  @otro]) stale?(etag:  [current_user,  @otromas]) Sunday, March 3, 13
  • 13. EN RAILS •CON ETAGGER etag  {  current_user  } stale?(etag:  modelo) stale?(etag:  otro) stale?(etag:  otromas) Sunday, March 3, 13
  • 14. EN RAILS •EN AC PERFORACIONES etag  {  [current_user,  ENV[‘COMMIT_HASH’]  } stale?(etag:  modelo) stale?(etag:  otro) stale?(etag:  otromas) Sunday, March 3, 13
  • 15. Rails Fragment Caching -­‐cache  ‘foo’  do...end -­‐cache  modelo  do...end -­‐cache  [reporte,  ‘inbox’]  do..end # File actionpack/lib/action_controller/caching/fragments.rb, line 51 def fragment_cache_key(key) ActiveSupport::Cache.expand_cache_key( key.is_a?(Hash) ? url_for(key).split("://").last : key, :views) end Sunday, March 3, 13
  • 16. RUSSIAN DOLL CACHING -­‐  cache  [reporte,  ‘perforaciones’]  do    -­‐  perforacion.each  do  |p|        -­‐  cache  perforacion  do            %h1=  perforacion.titulo            %p=  perforacion.whatever Sunday, March 3, 13
  • 17. TIPS FRAGMENT CACHING •Aplicar a cosas que no dependan del usuario actual •Usar cache_digests + memcached Sunday, March 3, 13
  • 18. CONCLUSIONES •HTTP CACHING: •CACHE LOCAL AL USUARIO •AHORRA: •LATENCIA •ANCHO DE BANDA, •TIEMPO DE RESPUESTA DEL SERVIDOR Sunday, March 3, 13
  • 19. CONCLUSIONES •FRAGMENT CACHING: •CACHE GLOBAL DE LA APP •AHORRA: •HITS A LA BD •CALCULOS •RENDERING Sunday, March 3, 13
  • 20. BONUS TRACK def prefetch(url) content_tag("script", %Q{ $("<link href='#{escape_javascript(url)}' rel='subresource'/>").appendTo('head') }.html_safe ) unless current_page?(url) end def tab_detalle_reporte(text, opts = {}) collection = opts[:collection] || text.downcase.pluralize url = send("reporte_#{collection}_path", estado, reporte) tab_title(opts.merge!( name: text, href: url, active: tab == collection )) + prefetch(url) end Sunday, March 3, 13