Chad 2010-06-17

The sfDoctinePlugin itself encapsulated a class for manipulating the PECL Memcache module1.

With it, we can connect to any cache server that installed Memcached ( a daemon in Linux, my colleague Kim told me that there's also a Windows version2.)

Code - PHPPlain Text
 
  1. // configuration.calss.php  
  2.   
  3.     public function configureDoctrine(Doctrine_Manager $manager)  
  4.     {  
  5.             // ...            
  6.             $servers = array(  
  7.                 'host' => sfConfig::get('app_memcached_server_host'),  
  8.                 'port' => sfConfig::get('app_memcached_server_port'),  
  9.                 'persistent' => true  
  10.             );  
  11.       
  12.             $option = array(  
  13.                 'servers' => $servers,  
  14.                 'compression' => false  
  15.             );  
  16.   
  17.             $cacheDriver = new Doctrine_Cache_Memcache($option);  
  18.             $manager->setAttribute(Doctrine::ATTR_RESULT_CACHE, $cacheDriver);  
  19.             // ...    

 

Then we can use it to cache data:

Code - PHPPlain Text
 
  1. // try to get from cache  
  2. $manager = Doctrine_Manager::getInstance();  
  3. $cacheDriver = $manager->getAttribute(Doctrine::ATTR_RESULT_CACHE);    
  4. # method 1  
  5. $aryVehicleUrls = $cacheDriver->fetch('vehicle_urls');  
  6. if(!$aryVehicleUrls){  
  7.     $aryVehicleUrls = array();  
  8. }  
  9. if(isset($aryVehicleUrls[$v['id']])){  
  10.     return $aryVehicleUrls[$v['id']];  
  11. }  
  12.   
  13. // not found in cache, get data  
  14. // ...  
  15.   
  16. // cache it  
  17. $aryVehicleUrls[$v['id']] = $slug;  
  18. $cacheDriver->save('vehicle_urls',$aryVehicleUrls,null,true);  

But then I found that it became very slow ( much slower than without cache)!! 

I couldn't figure out why this would happen, then I try to change the way to store the data, from putting a lot of records into one array and then cache it, to directly cache the records individually:

Code - PHPPlain Text
 
  1. // ...  
  2. # method 2  
  3. $vehicleUrl = $cacheDriver->fetch('vehicle_url_'.$v['id']);  
  4. if($vehicleUrl){  
  5.     return $vehicleUrl;  
  6. }  
  7.   
  8. // not found in cache, get data  
  9. //...  
  10.   
  11. // cache it  
  12. $cacheDriver->save('vehicle_url_'.$v['id'],$slug,null,true);  

Now this works much faster, even faster than without cache (which is supposed to be...), though it's still slow when it do the first run, which means to save the data into cache.

Below are the figures I tested out:

 

So, it seems that it's not a good idea to store data with complicated structure into Memcache. If you are going to cache a lot of records, it's better to give each record a cache key and cache them directly.

 

1. PECL Memcache module, http://pecl.php.net/package/memcache

2. Memcached for Windows, http://jehiah.cz/projects/memcached-win32/files/memcached-1.2.1-win32.zip