method_cache: Let’s cache some stuff !

Building a large-scale web application can be troublesome. It leaves us facing all sorts of optimization problems. A very good – but no easy – solution is to use caching. Caching is a real saver as it can help with minimizing

  1. Database queries
  2. String operations

which are the two main problems that can affect the performance of a web application.

A common problem that developers always face is having to call a method regularly knowing that its results rarely change and its cost is always high. More on that in the following code

class User < ActiveRecord::Base
  def costy_method
    #some real heavy calculation that takes alot of resources
    #to complete
    #this method is called regularly and its results rarely change
  end
end

Calling user.costy_method with all its costs and behavior appears to be a point that can be optimized. How about caching its result? The user.costy_method needs to be modified so that it caches its result. A common practice for Ruby developers is to cache the result in an instance variable the following way

def costy_method
  @costy_method_result || = #the actual calculations
end

What if there were more methods like this? They’ll all have to be rewritten so as to cache their results. This would be a tedious task with a lot of repeated code which violates DRY concept. Why not have a simpler solution for this particular problem? We wrote the method_cache plugin. Let’s see how it works

class User < ActiveRecord::Base
  def costy_method
    #some real heavy calculation that takes alot of resources
    #to complete
    #this method is called regularly and its results rarely change
  end
  caches_method :costy_method
end

and voila, every time user.costy_method is called, you’ll get the value you expect normally but this time at a much less cost.
caches_method :costy_method builds a 2 level cache(a note on that later), it caches the result in an instance variable inside the user object and it also saves a copy in your fragment_cache_store which can be of several types (a file store, a memory store or memcached). Now if the same user instance is used to call user.costy_method we’ll get a huge performance gain as it will just cost u as much as it costs to retrieve any instance variable. If another user instance is used, the first time you call user.costy_method the value will be retrieved from your cache store and put for your convenience in the instance variable. If the value can’t be retrieved from an instance variable or the cache store the real costy_method implementation is executed to get that value.

Another convenience method is expire_method :method_name which can be used like user.expire_method :costy_method. This method will simply clear the instance variable and cache store entry if they’re available so that next time user.costy_method is called, a new value will be calculated.

Mido – Eng. Muhammed Ali – wrote this plugin. I pretty much loved the simplicity by which this will allow us to cache stuff.

More on the plugin features
We needed to be able to cache the results for certain amount of time. The problem is that the default MemCacheStore didn’t support that. So again with some Ruby magic I overrided the MemCacheStore code so that I can write some stuff like the following
caches_method :costy_method, :until => :midnight
or
caches_method :costy_method, :for => 20.days

After using the plugin internally for a while we decided it’s best if others can make use of it and also contribute. We’ve setup a project on RubyForge which can be found here.

In its current form, the plugin provides the following extensions to ActiveRecord Objects
caches_method :method_name
caches_class_method :method_name
and for expiring the cache
instance.expire_method :method_name
Class.expire_instance_method :method_name, id
Class.expire_class_method :method_name

More on the 2 level cache mentioned before, for class methods, we cached the results in static variables but this was a deal breaker once we used several mongrels to serve our application as it’s impossible to synchronize the expiry of the static variables on the different mongrels so we decided it was enough to use the fragment cache store as our only store when dealing with class methods.

I think it would be nice to refactor the plugin so as to be able to use it with all classes not just ActiveRecord::Base descendants. This would require some minor changes such as defining a method that defines an instance uniquely. In case of ActiveRecord objects, it’s just the id.

Update
I’ve updated the plugin so it uses the Rails cache store introduced in Rails 2.1. I’ve also moved the plugin to GitHub and it can be found here.

To install it

ruby script/plugin install git://github.com/humanzz/method_cache.git
Technorati Tags: ,,

Advertisements

Have a cookie, Smile and Flash !

Quite often, Ruby on Rails developers use the flash object to store objects for the following request. Flash’s most common use is for displaying messages to users after redirections. Flashes are usually rendered in the application’s layout.

Consider the following 2 scenarios that will stop flashes from working properly

  1. AJAX requests.
    Flash will simply be ignored as it’s rendered in the layout. One way to handle this is to have the AJAX response carry both the normal response + the flash message and have the JavaScript at the client figure out which is which then display the flash message and handle the normal response. This is a bit cumbersome but doable.
  2. Responding with cached pages.
    What if the server responds with a cached page? The layout will never be rendered and so will the flash messages.

So, what we really need is a solution that doesn’t rely on the rendering of the layout or of partial responses.

Have a cookie and be a happy – hopefully not so fat – man 🙂
Really, what about storing the flash messages in a cookie? Have JavaScript check that cookie and display the message accordingly?
How do we write the flash message into a cookie? What about an after_filter that writes the flash message into a cookie and then wipes the flash object clean?

So, we need to edit 2 files

  1. ApplicationController
    class ApplicationController < ActionController::Base
      .
      .
      after_filter :set_flash_cookies
      private
     
      def set_flash_cookies
        if(flash[:error])
          cookiesNotification('error', flash[:error])
          flash[:alert] = nil
        elsif(flash[:note])
         cookiesNotification('note', flash[:note])
         flash[:info] = nil
        end
      end

      def cookiesNotification(type, msg)
        begin
          cookies[:notification] = {:type => type, :message => msg.to_s}.to_json
        rescue => e
          #hanlde the exception
        end
      end
    end

    The previous code adds the flash message into a cookie and wipes the flash object clean.

  2. The application layout
    First, we’ll have a function that extracts the message out of the cookie if present and display the message then delete the cookie.

    processNotifications = function(){
      if(Cookies.readCookie("notification")){
        //Cookies is a namespace that has a couple of function that abstracts processing cookies
        eval("notification = " + unescape(Cookies.readCookie("notification").replace(/+/g," ")));
        //show the notification in its normal place
        showNotification(notification.type, notification.message);
        Cookies.eraseCookie("notification");
      }
    }

    We need to make sure that this function is called at proper times i.e. when pages are loaded and after AJAX calls are completed. This can be achieved using the following code which uses prototype javascript library

    //for page loads
    document.observe("dom:loaded", function(){processNotifications();});
    //for AJAX calls
    Ajax.Responders.register({ onComplete: function(){ processNotifications();}});

Who said cookies were bad ?!

Technorati Tags: ,,

Martian Headsets

Web standards and different browsers implementation have always been a nightmare for software developers. Joel Spolsky gives a nice explanation about the current situation.

Check his blog entry "Martian Headsets".

FolderShare is now Windows Live FolderShare Beta (This time for real)

One of my favorite programs is FolderShare. For those who don’t know, it is a small program that sits in your tray but gives you great features

  1. The ability to share certain folders – Libraries in FolderShare terminology – with any number of your friends
  2. Assign people who’re participating in your libraries different privileges like reader, contributor or editor.
  3. Synchronize different libraries across your different computers
  4. Remote Access to any of your computers’ file system.
    That’s a real cool feature. I leave my home PC online 24×7. I can so easily access its files through a real simple interface from foldershare’s website.

Microsoft bought FolderShare in 2005 and it was supposed to be integrated into Windows Live services but for the past 2 years there were no updates at all to FolderShare. That didn’t bother me, I just loved the service the way it was. Today, however, the foldershare website has been updated at last to reflect the Windows Live brand and a new client is released. It can be downloaded from here. Check WL FolderShare blog.

 

There are no new features yet. However, I don’t think that would last for much longer. FolderShare website and service appears to have been using PHP but the updated version, naturally, uses ASP.NET.

A couple of features I’d love to see

  1. Integration with Windows Live ID
    Sign in once, use all WL services
  2. Forget about Windows Live Messenger Sharing Folders. Do the sharing through FolderShare
  3. FolderShare + SkyDrive. That would be a real interesting story. Have SkyDrive appear  as one of my computers in FolderShare so I can store Libraries on it, share with friends from it and sync my personal folders to it. That would just be great

I’m sure integration is WL ID is coming. It’s the only logical thing to do next. Integration with messenger seems logical to me too but will they do it anytime soon ?!
I really hope someone is already exploring the FolderShare + SkyDrive integration. It will just rock.

Silverlight 2 ‘Deep Zoom’

Did you try Microsoft Photosynth?!
If you didn’t then please go ahead. It’s just a beautiful way of navigating through very large collections of images to the extent of building 3D models of places and scenes shot by thousands of different cameras and people.

Did you try Google/Windows Live/Yahoo maps?!
I enjoy all the zooming and panning through the maps. Maps work by loading images as we navigate where they load only the relevant pieces.

Have you ever wanted to do something similar with a large collection of images you own ?!
Navigate through a large collection of images while saving bandwidth and only loading the images you want ?!

Meet Deep Zoom.
It’s just a fascinating piece of technology that allows you to create stunning user experiences using zoom and panning.

For some example sites check the following

You should have Silverlight 2 Beta 1 runtime in order to try it.

You can give it a try and upload some pictures of yours and try it at Windows Live PhotoZoom. More on that from Liveside.net can be found here.

For developers, you can create Silverlight applications that take advantage of the Deep Zoom technology so easily

  1. Grab Deep Zoom Composer from here and check the documentation
  2. Grab the sample from Expression Blog (it’s a real cool demo).

I was thinking about posting my demo application where I used several photos for lovely Angelina Jolie but then I searched for an example and I found a whole lot of them available. So if you struggle or something just search for Deep Zoom and I’m sure you’ll get what you want easily.

Now you are ready to go.

Internet Explorer 8 Beta 1 is released

Yesterday, IE 8 Beta 1 has been released in accordance with MIX08. Microsoft also released the awaited update of Silverlight, Silverlight 2.0. I haven’t check Silverlight 2.0 yet but the features list looks very promising for an RIA platform.
 
I just wanted to share a couple of quick thoughts about IE8
  1. I like how the domain name emphasized in the address bar to prevent phishing attacks
  2. For me, I’ve fell in love with developing web apps using firefox only because of firebug. Firebug rocks. I’m glad to see MS addressing this issue with the release of integrated developer tools though I don’t like how they did it in this release where the developer tools show in a separated window. It should be dockable to the bottom like firebug and the IE developer toolbar.
  3. A great thing about the developer tools, they allow you to emulate IE5, IE7 or – no emulation – IE8. That’s a real good thing for web developers who struggle to see the outcome of their work on multiple browsers.
  4. IE8B1 passed the acid2 test, but I feel it’s too slow where one sees the rendering details. I tried that with Firefox 3 beta and I didn’t see such slowliness

I haven’t installed IE8 at home yet. I need to try it more thouroughly as I think in addition to the developers features they added a couple of user friendly ones.

I also need to check Silverlight 2.0. The ease with wich one can develop a real attractive fully functional RIA using Silverlight is just amazing. Check ScottGu’s Blog posts on Silverlight 2.0 tutorials and using Blend 2.5 with them.

A feature that I wish they had was to search in history, favorites and feeds. I love the search box in vista’s start menu and the search for contacts in WL Messenger. If only they made something similar in IE8.

Update
check these entries from IEBlog

The funny thing is, a couple of Microsoft sites that talk about IE8 don’t show well in IE8 !

A-G-A-M-Y Agamy Model School

A-G-A-M-Y agamy model school A-G-A-M-Y agamy model school
We are part of the school, we will do our best, to make it the best, and show the rest that we caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaan
Agamy Model School
God save the school our model school, God save the school our model school
Agamy Model Schooooooooooooooooooooooooooooooooooooool