Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Aila!.. Caching in Rails.

Aila!.. Caching in Rails.

I will be speaking on why caching is important and how we can scale up the Rails app using different caching strategies like page, action & fragment. I will also speak on how we can improve the performance in the simplest way by using instance variable caching for expensive command’s result.

Santosh Wadghule

August 06, 2016
Tweet

Other Decks in Programming

Transcript

  1. Caching It is a process of storing data so future

    requests for that data can be served faster
  2. Caching It is a process of storing data so future

    requests for that data can be served faster Improves user experience
  3. Caching It is a process of storing data so future

    requests for that data can be served faster Saves a lot money and other hardwares Improves user experience
  4. Caching It is a process of storing data so future

    requests for that data can be served faster Saves a lot money and other hardwares Keeps you and your users happy :) Improves user experience
  5. Main Resource Cache Memory Client A A A A A

    Main Resource Cache Memory Requester A A A A A First Request Future Requests
  6. CACHING IN RAILS BEFORE CACHING: FIRST BOOST YOUR RAILS APP

    ▸ Avoid n+1 queries. ▸ Index on foreign keys. ▸ Instance variable caching ▸ Load only required JavaScript files in web pages. ▸ Minify and ZIP stylesheets and JavaScript files.
  7. There are only two hard things in Computer Science: cache

    invalidation & naming things Phil Karlton CACHING IN RAILS
  8. CACHING IN RAILS CACHING IN RAILS ▸ Basic Caching (Page,

    Action & Fragment Caching) ▸ Low Level Caching ▸ Alternative cache stores ▸ SQL Caching ▸ Conditional GET support
  9. CACHING IN RAILS INVALIDATING PAGE CACHING ▸ Non model pages

    need to be deleted manually. ▸ expire_page helper method ▸ expire_page action: “index” ▸ expire_page action: “show”, id: @post ▸ ‘Sweepers’ also helps to invalidate the cache
  10. class HomeController < ApplicationController before_action :log_it def index if request.format.json?

    render json: { text: "Home Page" } else render end end private def log_it logger.info("") logger.info(">>>> BEFORE ACTION CODE <<<<") logger.info("") end end
  11. class HomeController < ApplicationController before_action :log_it caches_action :index, if: Proc.new

    { !request.format.json? }, expires_in: 30.seconds def index if request.format.json? render json: { text: "Home Page" } else render end end private def log_it logger.info("") logger.info(">>>> BEFORE ACTION CODE <<<<") logger.info("") end end
  12. <table> <thead> <tr> <th width="150">Name</th> <th width="150">Amount</th> </tr> </thead> <tbody>

    <% @products.each do |product| %> <% cache(product) do %> <tr> <td width="150"> <%= product.name %> </td> <td width="150"> <%= product.amount %> </td> <td> <%= link_to 'Edit ', edit_product_path(product) %> </td> </tr> <% end %> <% end %> </tbody> </table>
  13. CACHIN IN RAILS. FRAGMENT CACHING ▸ `expire_fragment(‘name_of_cache’)` is also responsible

    to expire the fragment. ▸ `cache_if` & `cache_unless` for conditional fragment caching.
  14. # product view template <% cache product do %> name:

    <%= product.name %> <%= render product.comments %> <% end %> # comment view template <% cache comment do %> <%= render comment %> <% end %>
  15. class Product < ActiveRecord::Base has_many :comments end class Comment <

    ActiveRecord::Base belongs_to :product, touch: true end
  16. App is damn slow when we fire request to Spark

    service to get the spark listings and we also sometimes get Spark API limit error. Issue
  17. class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}",

    expires_in: 24.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end
  18. class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}",

    expires_in: 12.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}", expires_in: 12.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}", expires_in: 12.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}", expires_in: 12.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end Saved money
  19. class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}",

    expires_in: 12.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}", expires_in: 12.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end Saved money Saved response time as well
  20. class Listing < ApplicationRecord LIMIT = 20 def self.spark_listings(page) Rails.cache.fetch("spark_listing/page=#{page}",

    expires_in: 12.hours) do SparkApi::ListingCart.listings(pagination: 1, page: page, limit: LIMIT) end end end Saved money Saved response time as well Awesome No?
  21. CACHIN IN RAILS. SQL CACHING ▸ Inbuilt Rails Feature ▸

    SQL Caching will be valid per request ▸ DON’T NEED TO ANYTHING, Rails will take care of it
  22. CACHIN IN RAILS. CACHE STORES ▸ Cache stores - memory_store,

    file_store, mem_cache_store, null store, and user defined custom store ▸ By default file_store is enabled
  23. CACHIN IN RAILS. CACHE KEYS ▸ Hold any object which

    responds to either cache_key or to_param ▸ e.g. Rails.cache.read(site: "mysite", owners: [owner_1, owner_2])
  24. CACHIN IN RAILS. CONDITIONAL GET SUPPORT. ▸ Needs these headers

    HTTP_IF_NONE_MATCH & HTTP_IF_MODIFIED_SINCE to be set ▸ Sever matches these headers against Etag & last_modified respectively ▸ Rails provides `stale?` & `fresh_when` helpers