4bb774de244da2d6e7f39a189b905077

i was getting serious performance problem with one of my projects. so i came up with a simple fragment cache implementation on ruby on rails. i wrote another method which was used instead of "render" method.

as i had mongrel backed deployment, so i could get shared memory advantage. as you know mongrel under production mode it keeps only single instance of all models.

# i use this method instead of "render"
render_from_cache_or_render(:cache_key =>”cache key”, :cache_expire_after => ConstantHelper::TAG_CLOUD_EXPIRED_IN, # minute

# implementation
def render_from_cache_or_render(p_args)

    return render(p_args) if true == p_args[:cache_off]

    # check from cache
    cache_key = p_args[:cache_key]
    cached_content = CacheService.get_cache(cache_key)

    if not cached_content.nil? and not cached_content.empty?
      return cached_content
    else
    content = render(p_args)
    
    # cache expire time if defined
    cache_expire_time_in_minutes = p_args[:cache_expire_after] || 60
      CacheService.add_cache(cache_key, cache_expire_time_in_minutes, content)
      return content
    end
end


# complete source code of cache service
module Cache
    class Item
      attr_accessor :key, :expire_time, :content, :created_on

      def initialize(p_key, p_expire_time, p_content)
        @key = p_key
        @expire_time = p_expire_time * 60 # in minutes
        @content = p_content
        @created_on = Time.now
      end
    end
end

class CacheService
    @@CACHES = {}
    @@CACHE_EXPIRE_TIMES = {}

    def self.add_cache(p_key, p_expire_time, p_content)
      cache_item = Cache::Item.new(p_key, p_expire_time, p_content)
      @@CACHES[p_key.to_sym] = cache_item
    end

    def self.get_cache(p_key)
      # load content from cache
      cached_content = @@CACHES[p_key.to_sym]
      return nil if cached_content.nil?

      # verify cache validity
      return cached_content.content if not expired?(cached_content)
      return nil
    end

    private
    def self.expired?(p_cache)
      # find time difference
      time_difference = Time.now - p_cache.created_on
      return true if time_difference > p_cache.expire_time
    end
 end

Refactorings

No refactoring yet !

5170ca260dbd2cdfd5a887a4dba7636f

Jeremy Weiskotten

November 22, 2007, November 22, 2007 15:11, permalink

1 rating. Login to rate!

Just a refactoring of the expired? method.

def self.expired?(p_cache)
  p_cache.created_on < p_cache.expire_time.seconds.ago
end
Bfec5f7d1a4aaafc5a2451be8c42d26a

macournoyer

November 22, 2007, November 22, 2007 18:38, permalink

No rating. Login to rate!

Why not used action caching ? http://api.rubyonrails.org/classes/ActionController/Caching/Actions.html
Or even better, page caching and play w/ the Expires header.

4bb774de244da2d6e7f39a189b905077

we4tech

November 23, 2007, November 23, 2007 05:01, permalink

No rating. Login to rate!

hi @macournoyer,
thanks for your comment,
actually i didn't know about ActionController::Cache related option.
i was looking for some solution which has higher level abstraction and flexibility.

looking at the documentation, i think it is lacking some features which is more relevant with my project -
1. not event driven (which i will provide on my implementation)
2. couldn't find anyway to set cache expire time.

so far i found the follow good features -
1. supports multiple implementation
2. supports way to invalidate the fragment.

and again thanks for pointing action controller cache.

best wishes,

4bb774de244da2d6e7f39a189b905077

we4tech

November 23, 2007, November 23, 2007 05:04, permalink

No rating. Login to rate!

hi @jeremy
i was trying to figure out what you did on your refactoring suggestion.
perhaps something is wrong, i couldn't find "seconds" method from "Time" class.
best wishes,

5170ca260dbd2cdfd5a887a4dba7636f

Jeremy Weiskotten

November 23, 2007, November 23, 2007 23:46, permalink

1 rating. Login to rate!

@we4tech: Rails' ActiveSupport module adds some methods to standard Ruby classes. A lot of it is really helpful -- you should familiarize yourself with it all.

This method was actually added to Ruby Numeric classes. See http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Numeric/Time.html

Don't forget to rate my refactoring if you think it helps!

4bb774de244da2d6e7f39a189b905077

we4tech

November 24, 2007, November 24, 2007 06:28, permalink

No rating. Login to rate!

hi @jeremy,
thank you for your link, it is really helpful :)

Your refactoring





Format Copy from initial code

or Cancel