Ruby on Rails has good out-of-the-box caching. The vast majority of the time it is all you need: it reliably works in controllers, domain logic, models (though I’d discourage it), and most importantly views.
However, Rails’ caching can slow down if you have to call the cache frequently (memoize!) or cache a large value. The latter can become very slow, especially a large set of interrelated ActiveRecord model instances. Recently I observed the serialization and deserialization times for a tree of around 1,000 model instances were an order of magnitude greater than the round trip time to the cache: the cache took <1ms, but deserializing the tree of object instances took over 100ms.
Keep it in memory
The solution is to keep the objects cached in memory on the Ruby heap. That way you never need to pay (de)serialization costs. Rails provides a
Module.thread_mattr_accessor method which makes it easy to build a trivial thread-safe cache service.
module ValueCache extend self thread_mattr_accessor :cached_value def value if cached_value && !expired? return cached_value end self.cached_value = compute_value cached_value end end
Rails’ implementation ensures every thread has its own storage location for
cached_value; therefore this should be thread-safe (assuming
#compute_value can safely run both concurrently and in parallel). And that assertion is supported by the fact that I haven’t observed any unsafe behavior in production.