Skip to content

Pitfalls of Rails fragment caching with memcached

Fragment caching is a powerful technique for improving performance of your web application. Rails site describes in detail how to apply this technique.

Rails are providing developers with really excellent abstractions, but it’s always good to know what’s under the hood and how it all works.

There are a few things that might potentially cause bugs in your code, or waste your time (speaking from my own experience). So here goes:

1. Beware of globally keyed fragments

Let’s take example from Rails tutorial:

<% cache do %>
  All available products:
  <% Product.all.each do |p| %>
    <%= link_to p.name, product_url(p) %>
  <% end %>
<% end %>

Now if you need to deal with a multi-language site you might want to make cache fragment language dependent. What might seem a convenient solution:

<%- cache([user.locale.to_s]) do -%>

will turn into a source of very interesting problems. While calling the cache method without parameters will automatically create a controller/action specific cache key, calling it with a key will make this fragment a globally keyed fragment. Cache key in the first case is going to look like “views/localhost:3000/controller-name”, and in the other case “views/en” – this is not as unique identifier any more.

While automatic cache key naming provided by rails is very convenient, it is very easy to run into a problem with duplicate cache key names used in different places.

2. Another pitfall of automatic cache key naming is that you shall never assume that when creating a cache with global key you can later find it using e.g. telnet interface to memcache. Example – add

<%- cache('unique_cache_key') do -%>
<%- end -%>

in your view and then try to read directly from memcache:

$ telnet localhost 11211
GET unique_cache_key
END

At the same time

GET views/unique_cache_key

will work. It’s easy to make this mistake trying to check or delete cache keys directly from memcache when using Rails cache methods.

3. delete_matched is not supported by memcached (see rails/activesupport/lib/active_support/cache/mem_cache_store.rb)

In practice that means that if you’re using memcached as Rails cache engine and trying to delete or expire fragment cache using standard Rails methods and regexp – you’ll fail.

expire_fragment(/base\/xyz.*/)

will fail miserably. Ideal solution is not to use explicit cache expiration, but rather create cache keys in such a way that doesn’t require expiration. Alternatively it’s possible to use extensions implementing delete_matched for memcached (haven’t tried it myself though).

Tip: one very useful tool for checking memcached is peep by Evan Weaver – allows you to peek into the cache and see what’s really cached and how it is used.

Share

3 Comments

  1. buy tramadol india buy tramadol with mastercard buy tramadol no prescription online jil’s dress center by vi dodge for miss paper is made of poly5 http://law1949.com/forum.php?mod=viewthread&tid=13355835

    Saturday, June 1, 2013 at 14:00 | Permalink
  2. Jocelyn wrote:

    I am now not certain where you are getting
    your info, but great topic. I needs to spend a
    while studying more or understanding more. Thanks for magnificent info I used to
    be looking for this info for my mission.

    Thursday, June 5, 2014 at 19:52 | Permalink
  3. My brother suggested I might like this blog. He was totally right.
    This post actually made my day. You cann’t imagine simply how much time I had spent for this info!
    Thanks!

    Friday, August 1, 2014 at 17:47 | Permalink

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*