<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:gd="http://schemas.google.com/g/2005" xmlns:georss="http://www.georss.org/georss" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-4720634742521623111</atom:id><lastBuildDate>Thu, 19 Sep 2024 12:21:46 +0000</lastBuildDate><category>Development</category><category>Magento</category><category>System Administration</category><category>performance</category><category>Bash</category><category>Ubuntu</category><category>Varnish</category><category>Web</category><category>Zend Framework</category><category>linux</category><category>trip to iop</category><category>wireless</category><title>Memoir of a Magento developer</title><description>A new adventure has begun. Blogging about my experience with Magento, Ajax, JavaScript and general development</description><link>http://www.kingletas.com/</link><managingEditor>noreply@blogger.com (Anonymous)</managingEditor><generator>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><language>en-us</language><itunes:explicit>no</itunes:explicit><itunes:subtitle>A new adventure has begun. Blogging about my experience with Magento, Ajax, JavaScript and general development</itunes:subtitle><itunes:category text="Education"/><itunes:owner><itunes:email>noreply@blogger.com</itunes:email></itunes:owner><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-2137874471316523972</guid><pubDate>Wed, 01 Aug 2012 16:53:00 +0000</pubDate><atom:updated>2012-08-01T12:53:29.947-04:00</atom:updated><title>Zend Queue with Magento</title><description>&lt;br /&gt;
Zend Queue with Magento&lt;br /&gt;
&lt;br /&gt;
By using Zend Queue with magento we can create an event driven asynchronus integration system. &lt;br /&gt;
&lt;br /&gt;
Just think about how much work you will offload from Magento when integrating with other systems and Magento itself.&lt;br /&gt;
&lt;br /&gt;
To keep things simple, let's pretend that you send emails to your customers everytime a new product gets added. Usually these products get added during the day which also happens to be when your customers are most active buying in the site. An alert about a new product is very important but you don't want to bug down your email server. That's where Zend Queue comes to the rescue. In this example I am using mysql to store the queue. If you follow the same example remember to create the tables first, these can be found under: lib/Zend/Queue/Adapter/Db/mysql.sql&lt;br /&gt;
&lt;br /&gt;
Also it will make more sense to use MemcacheQ or Apache ActiveMQ to offload mysql.&lt;br /&gt;
&lt;br /&gt;
Here's an example:&lt;br /&gt;
&lt;br /&gt;
In your observer class:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;public function sendEmails($observer){
 Mage::helper('OfflineSync')-&gt;setEmailsOffline($observer-&gt;getData('object_container'));

}
&lt;/pre&gt;&lt;br /&gt;
Helper class&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
 */

/**
* Description of Data
 *
* @author letas
 */
class ZendQueue_OfflineSync_Helper_Data extends Mage_Core_Helper_Data {

    protected $_name = "general";
    protected $_registry = array();
    protected $_queue = null;

    protected function getQueue() {
        if (!isset($this-&gt;_registry[$this-&gt;_name])) {
            $db = simplexml_load_file('app' . DS . 'etc' . DS . 'local.xml');
            $db = $db-&gt;global-&gt;resources-&gt;default_setup-&gt;connection;
            $queueOptions = array(
                Zend_Queue::NAME =&gt; "{$this-&gt;_name}",
                'driverOptions' =&gt; array(
                    'host' =&gt; $db-&gt;host,
                    'port' =&gt; $db-&gt;port,
                    'username' =&gt; $db-&gt;username,
                    'password' =&gt; $db-&gt;password,
                    'dbname' =&gt; $db-&gt;dbname,
                    'type' =&gt; 'pdo_mysql',
                    Zend_Queue::TIMEOUT =&gt; 1,
                    Zend_Queue::VISIBILITY_TIMEOUT =&gt; 1
                )
            );
            //// Create a database queue
            $this-&gt;_registry[$this-&gt;_name] = new Zend_Queue('Db', $queueOptions);
        }
        return $this-&gt;_registry[$this-&gt;_name];
    }

    public function getEmailsOffline() {
        try {
            $this-&gt;_name = "offline_email";
            //cache here / singlenton
            $this-&gt;_queue = $this-&gt;getQueue();
            foreach ($this-&gt;_queue-&gt;receive(); as $i =&gt; $message) {
               //send the real mail now

    //delete this message
   $this-&gt;_queue-&gt;deleteMessage($message);
            }
        } catch (Exception $e) {
            Mage::logException($e);
            return -1;
        }
        return 1;
    }

    public function saveEmailsOffline($emails) {
        if (isset($emails)) {
            if (is_array($emails) || is_object($emails)) {
                $emails = serialize($emails);
            }
            $this-&gt;_name = "offline_email";
            //cache here / singlenton
            $this-&gt;getQueue()-&gt;send($emails);
        }
        return $this;
    }

}
&lt;/pre&gt;&lt;br /&gt;
Now you can also configure a crontab in your module config.xml, your code may look like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt; Mage::helper('OfflineSync')-&gt;getEmailsOffline();
&lt;/pre&gt;&lt;br /&gt;
And you are done!!! Pretty simple right. &lt;br /&gt;
&lt;br /&gt;
The possibilities are endless. Orders / Customer exports. Everything can be queued up.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/08/zend-queue-with-magento.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-2374265431265609158</guid><pubDate>Wed, 01 Aug 2012 16:37:00 +0000</pubDate><atom:updated>2012-08-01T12:37:44.032-04:00</atom:updated><title>Cloning magento modules</title><description>Cloning magento modules will never this easy again.&lt;br /&gt;
&lt;br /&gt;
Today I wanted (read was forced) to create a module based on one of Magento's core. Literally I needed to clone some of the Magento modules and while the copy and paste is simple stuff, going class by class and file by file renaming and configuring files is not joke.&lt;br /&gt;
&lt;br /&gt;
So why do I need to clone it instead of just doing the usual OOP stuff Magento is so good at? Simply because the functionality is really different in most files and settings. So creating a payment method or paygate or giftcard module is easier when you have an skeleton to work with. Think about it, how different is paying with PayPal from Google Checkout? Functionality wise not that much, essentially they do the same thing but&amp;nbsp;implement&amp;nbsp;it differently.&lt;br /&gt;
&lt;br /&gt;
I remember someone (I am talking to you Alan Storm) saying: "It's programming - come up with a&amp;nbsp;canonical&amp;nbsp;way of doing it, put it in a function and forget it about it".&lt;br /&gt;
&lt;br /&gt;
So of course I decided that cloning magento modules was never going to be a hard task again.&lt;br /&gt;
&lt;br /&gt;
So from today&amp;nbsp;onward&amp;nbsp;cloning magento modules is going to be pretty simple (a least to me).&lt;br /&gt;
&amp;nbsp;Be warned there are some&amp;nbsp;hard-coded&amp;nbsp;paths here and little to none validation. Use at your own risk and needless to say don't use it on a production site. The script doesn't do about the app/etc/modules/module_name.xml so you have to do manually.&lt;br /&gt;
&lt;br /&gt;
Copy the following code into a file and save as &lt;b&gt;clone&lt;/b&gt;, no extensions needed:&lt;br /&gt;
&lt;pre class="brush: c"&gt;#!/bin/bash

ORIGINAL_NAME=$1;
NEW_NAME=$2;
NAMESPACE="MyCompany";

#copy the module
`cp -R app/code/core/Mage/$ORIGINAL_NAME app/code/local/$NAMESPACE/$NEW_NAME`
#lowercase both the original name and new name
lowercase_orig=`echo $ORIGINAL_NAME | tr '[A-Z]' '[a-z]'`
lowercase_new=`echo $NEW_NAME | tr '[A-Z]' '[a-z]'`
#Rename the class declaration and stuff
`grep -lr "$ORIGINAL_NAME" "app/code/local/$NAMESPACE/$NEW_NAME/" | xargs -d "\n" sed -i "s/$ORIGINAL_NAME/$NEW_NAME/g"`
`grep -lr "Mage" "app/code/local/$NAMESPACE/$NEW_NAME/" | xargs -d "\n" sed -i "s/Mage/$NAMESPACE/g"`
#rename the  the shorcuts
`grep -lr "$lowercase_orig" "app/code/local/$NAMESPACE/$NEW_NAME/" | xargs -d "\n" sed -i "s/$lowercase_orig/$lowercase_new/g"`
#rename the files
`find "app/code/local/$NAMESPACE/$NEW_NAME" -name "*$ORIGINAL_NAME*" -exec rename "s/$ORIGINAL_NAME/$NEW_NAME/g" {} \;`
&lt;/pre&gt;&lt;br /&gt;
The trick here is to use find and grep to find the old module name and class shorcuts and use sed and rename to change it to the new one. Notice that tr is used to lowercase the old and new name because we are doing case sensitive searches. Also rename and sed are only replacing the portion of the text they find.&lt;br /&gt;
&lt;br /&gt;
First let's make sure we can execute the file  &lt;br /&gt;
&lt;pre&gt;chmod +x clone (only need to do this once)&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
Then in the root of your Magento installation do:&lt;br /&gt;
&amp;nbsp;./clone module1 module2&lt;br /&gt;
&lt;br /&gt;
And then you will have it a brand new module cloned from Core to use as your starting point.&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/08/cloning-magento-modules.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-7969456266356094472</guid><pubDate>Wed, 01 Aug 2012 16:32:00 +0000</pubDate><atom:updated>2012-08-01T12:32:11.047-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Magento</category><category domain="http://www.blogger.com/atom/ns#">performance</category><title>Full Page cache with nginx and memcache</title><description>&lt;h2&gt;Full Page cache with nginx and memcache&lt;/h2&gt;&lt;p&gt;Since the cool kids at Google, Microsoft and Amazon researched how performance and scalability affect conversion rates, page load time has become the topic of every eCommerce store. &lt;br /&gt;
&lt;/p&gt;&lt;div&gt;Magento was once a resource hog that consumated everything available to it and you had to be a magician to pull off some awesome benchmarks without using any reverse proxy or full page cache mechanism. Creating a full page cache with nginx and memcache is really simple (right after hours of research). &lt;br /&gt;
&lt;br /&gt;
Words of warning first:&lt;br /&gt;
&lt;br /&gt;
Don't use this instead of varnish or Magento's full page caching. This implemenation of full page cache is very simple, heck it will be even troublesome to clean the cache consistently because guess what, there is no holepunching but you could enhance the configuration file to read cookies and serve directly from the backend server instead. &lt;br /&gt;
&lt;br /&gt;
Another problem is that you'll need to ensure that a TwoLevel caching is used to be able to flush specific urls.&lt;br /&gt;
&lt;br /&gt;
Now that is out of the way, let's focus on the matter at hand.&lt;br /&gt;
&lt;br /&gt;
I have tried this configuration file with both Magento enterprise and community and also with WordPress. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;#memcache servers load balanced
upstream memcached {
        server     server_ip_1:11211 weight=5 max_fails=3  fail_timeout=30s;
        server     server_ip_2:11211 weight=3 max_fails=3  fail_timeout=30s;
        server    server_ip_3:11211;
 keepalive 1024 single;
}
#fastcgi - little load balancer
upstream phpbackend{
 server     server_ip_1:9000 weight=5 max_fails=5  fail_timeout=30s;
        server     server_ip_2:9000 weight=3 max_fails=3  fail_timeout=30s;
        server    server_ip_3:9000;
}
server {
    listen   80; ## listen for ipv4; this line is default and implied
    root /var/www/vhosts/kingletas.dev/www;
    server_name kingletas.dev;
    index index.php index.html index.htm;

    client_body_timeout  1460;
    client_header_timeout 1460;
    send_timeout 1460;
    client_max_body_size 10m;
    keepalive_timeout 1300;

    location /app/                { deny all; }
    location /includes/           { deny all; }
    location /lib/                { deny all; }
    location /media/downloadable/ { deny all; }
    location /pkginfo/            { deny all; }
    location /report/config.xml   { deny all; }
    location /var/                { deny all; }

   location ~* \.(jpg|png|gif|css|js|swf|flv|ico)$ {
     expires max;
     tcp_nodelay off;
     tcp_nopush on;
    }
    location / {
  
        try_files $uri $uri/ @handler;
        expires 30d;
    }
   location @handler {
 rewrite / /index.php;
    }

    location ~ \.php$ {
        if (!-e $request_filename) { 
            rewrite / /index.php last; 
        }  
        expires        off; ## Do not cache dynamic content
        default_type       text/html; charset utf-8;
        if ($request_method = GET) { # I know if statements are evil but don't know how else to do this
            set $memcached_key $request_uri; Catalog request modal 
            memcached_pass     memcached;
            error_page         404 502 = @cache_miss;
            add_header x-header-memcached true;
  }
  if ($request_method != GET) {
   fastcgi_pass phpbackend;
  }
    }
    location @cache_miss {
        # are we using a reverse proxy?
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_max_temp_file_size 0;
        
        #configure fastcgi
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_send_timeout  5m;
        fastcgi_read_timeout 5m;
        fastcgi_connect_timeout 5m;
        fastcgi_buffer_size 256k;
        fastcgi_buffers 4 512k;
        fastcgi_busy_buffers_size 768k;
        fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code; 
        fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name; 
        fastcgi_param  PHP_VALUE "memory_limit = 32M";
        fastcgi_param  PHP_VALUE "max_execution_time = 18000";
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    location ~ /\. {
  deny all;
 }
}
#if you want to make it even better your own cdn
#server {
#      listen 80; 
#      server_name media.kingletas.dev;
#      root /var/www/vhosts/kingletas.dev/www;
#}
#server {
#      listen 80; 
#      server_name css.kingletas.dev;
#      root /var/www/vhosts/kingletas.dev/www;
#}
#server {
#      listen 80; 
#      server_name js.kingletas.dev;
#      root /var/www/vhosts/kingletas.dev/www;
#}
&lt;/pre&gt;&lt;br /&gt;
One major topic to remember is that nginx will try to read from memory not write to it. In other words you still need to write the contents to memcache. For WordPress this is what I did in the index.php&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: php"&gt;/**
* Front to the WordPress application. This file doesn't do anything, but loads
* wp-blog-header.php which does and tells WordPress to load the theme.
 *
* @package WordPress
 */

/**
* Tells WordPress to load the WordPress theme and output it.
 *
* @var bool
 */
ini_set("memcache.compress_threshold",4294967296); //2^32
ob_start();

define('WP_USE_THEMES', true);

/** Loads the WordPress Environment and Template */
require('./wp-blog-header.php');

$buffer = ob_get_contents();

ob_end_clean();

$memcache_obj = memcache_connect("localhost", 11211);
memcache_add($memcache_obj,$_SERVER['REQUEST_URI'],$buffer,0);

echo $buffer;

&lt;/pre&gt;&lt;br /&gt;
Notice that I had to change the memcache.compress_threshold setting to HUGE number, that is because memcache will ignore the no compress setting when this threshold is exceeded and compress the content, while this is good and dandy the results in the browser are not.&lt;br /&gt;
&lt;br /&gt;
So there you have it an easy way to implement full page caching with nginx and memcache for WordPress or Magento and the rest of the framework world.&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/08/full-page-cache-with-nginx-and-memcache.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-216978264644112794</guid><pubDate>Sat, 28 Jul 2012 21:21:00 +0000</pubDate><atom:updated>2012-07-28T17:26:51.952-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Bash</category><category domain="http://www.blogger.com/atom/ns#">linux</category><category domain="http://www.blogger.com/atom/ns#">System Administration</category><category domain="http://www.blogger.com/atom/ns#">Ubuntu</category><category domain="http://www.blogger.com/atom/ns#">wireless</category><title>Connect to a wireless network through the command line</title><description>&lt;div&gt;&lt;p&gt;Sometimes you decide that you don't want to use any GUI to connect to your wireless network, especially when it doesn't seem to work.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;One of the main benefits of Linux and any other Unix based operating system is its ability to empower users to do things on their own.&lt;br /&gt; So tonight when the latest Ubuntu updates broke my laptop's wireless, I decided to write a little script to fix it.&lt;/p&gt;
&lt;br /&gt;
&lt;span class="fullpost"&gt;
&lt;p&gt;You will need to know the following:&lt;/p&gt;
&lt;ul&gt;
         &lt;li&gt;ifconfig&lt;/li&gt;
         &lt;li&gt;iwlist&lt;/li&gt;
         &lt;li&gt;iwconfig&lt;/li&gt;
         &lt;li&gt;dhclient&lt;/li&gt;
&lt;/ul&gt;

Find your network interface, unless you know it (my laptop is always wlan0) &lt;br /&gt;
&lt;pre class="brush: c"&gt;
ifconfig
&lt;/pre

if you don't see your network interface but you know it by hard try this:&lt;br /&gt;
&lt;pre class="brush: c"&gt;
ifconfig NETWORK_ID up
&lt;/pre&gt;

Find the network you want to connect to:

&lt;pre class="brush: c"&gt;
iwlist network_interface scan
&lt;/pre&gt;
&lt;br /&gt;
Let' configure your network card&lt;br/&gt;
&lt;pre class="brush: c"&gt;
iwconfig NETWORK_ID essi "NAME" key s:password
&lt;/pre
&lt;br /&gt;or&lt;br /&gt; 
&lt;pre class="brush: c"&gt;
iwconfig network_interface essi "NAME" key hex_password
&lt;/pre

&lt;br /&gt;

Now all we need is to get the IP from the DHCP server:
&lt;br /&gt;
&lt;pre class="brush: c"&gt;
dhclient network_interface
&lt;/pre&gt;
&lt;br /&gt;
You could have it all in a script:
&lt;pre class="brush: c"&gt;
#!/bin/bash
ifconfig wlan0 up
iwconfig wlan0 essi "$1" key s:$2
dhclient wlan0
&lt;/pre
&lt;br /&gt;
Save it as wireless_up and then chmod a+x wireless_up. &lt;br /&gt;
Now you just need to either do ./wireless_up network_id my_password or bash wireless_up network_id my_password in the same directory. You could also move the script to a global location or add the directory where you have it as part of your local path. The choice is yours. 

&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/07/connect-to-wirless-network-through.html</link><author>noreply@blogger.com (letas)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-3864698014662117444</guid><pubDate>Fri, 27 Jul 2012 20:47:00 +0000</pubDate><atom:updated>2012-07-27T16:59:58.134-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Magento</category><category domain="http://www.blogger.com/atom/ns#">performance</category><category domain="http://www.blogger.com/atom/ns#">System Administration</category><title>Dirt cheap way to make magento fly</title><description>&lt;div&gt;
   There are several ways to accomplish the same task and some are more elegant than others. &lt;br /&gt;
   This one makes any Magento community edition fly and is cheap and quick (read no Magento compliant - because it modifies the templates)&lt;br /&gt;
   In other words while this trick can help you boost your Magento store server response I am not too proud of it.&lt;br /&gt;
   &lt;br /&gt;
   Why is that a big deal? I am not a huge fan or changing templates, even if they are "allowed". 
   &lt;br /&gt;
   But let's forget about that and get down to business&lt;br /&gt;
   &lt;span class="fullpost"&gt;
      Your actual cache helper class
      &lt;pre class="brush: php"&gt;
class Performance_CacheHelper_Helper_Data extends Mage_Core_Helper_Data {

    //###########################################
    //Cache related functions and variables
    //###########################################
    /**
     * cache key
     * @var string|mixed 
     */
    protected $key;

    /**
     *
     * @var Mage_Core_Model_Cache 
     */
    protected $_cache;

    /**
     * data container
     * @var string|mixed 
     */
    protected $data;
    protected $tags = array(__CLASS__);

    public function canUseCache() {
        //verify if the cache is enabled
        return Mage::app()-&gt;useCache('block_html');
    }

    /**
     * Gets the cache object
     * @return Mage_Core_Model_Cache 
     */
    protected function _getCacheObject() {
        if (!$this-&gt;_cache) {
            $this-&gt;_cache = Mage::app()-&gt;getCache();
        }
        return $this-&gt;_cache;
    }

    public function getData() {
        return $this-&gt;data;
    }

    public function setData($data) {
        $this-&gt;data = $data;

        return $this;
    }

    public function getKey() {
        return $this-&gt;key;
    }

    public function setKey($key) {
        $this-&gt;key = $key;
        return $this;
    }

    /**
     * saves data in a serialize format to cache under the name of this class if the cache can be used
     * @return Performance_CacheHelper_Helper_Data 
     */
    public function saveDataInCache() {
        if ($this-&gt;canUseCache()) {
            $cookie = Mage::getModel('core/cookie');
            $this-&gt;_getCacheObject()-&gt;save(
                    serialize($this-&gt;data), $this-&gt;key, $this-&gt;tags, $cookie-&gt;getLifetime());
        }
        return $this;
    }

    /**
     *
     * @param string $key
     * @return mixed
     */
    public function getDataFromCache($key) {
        $this-&gt;key = $key;
        return $this-&gt;_getCachedData();
    }

    /**
     * gets the data saved in cache, if it finds it then it unserializes itF
     * @param string|mixed $key
     * @return bool | string
     */
    protected function _getCachedData($key = null) {
        if ($key !== null) {
            $this-&gt;key = $key;
        }
        /**
         * clear the data variable 
         */
        $this-&gt;data = false;
        //ensure cache can be used
        if ($data = $this-&gt;_getCacheObject()-&gt;load($this-&gt;key)) {
            $this-&gt;data = unserialize($data);
        }
        return $this-&gt;data;
    }

}

&lt;/pre&gt;
      In your current template:
      &lt;pre class="brush: php"&gt;                
         //this code has been modified so the highligthing works right                   
        $helper = Mage::helper('cachehelper');
        $cachingEnabled = array('catalog');
        $key = md5(Mage::helper('core/url')-&gt;getCurrentUrl());
        $currentModule = Mage::app()-&gt;getRequest()-&gt;getModuleName();
        if (in_array($currentModule, $cachingEnabled)){
         if ($content = $helper-&gt;getDataFromCache($key)){
         //nothing do $content now has the data
         }else{
             $content = $this-&gt;getChildHtml('content');
             $helper-&gt;setKey($key)-&gt;setData($content)-&gt;saveDataInCache();
            
        }else{
         $content = $this-&gt;getChildHtml('content');
        }

&lt;/pre&gt;
      &lt;pre class="brush: html"&gt;
  &lt;div class="col-main"&gt;&lt;? echo $content; ?&gt;&lt;/div&gt;
&lt;/pre&gt;
      siege -t1m -c5 -b -d -i http://mage.dev/apparel
      &lt;br /&gt;
      &lt;b&gt;Examples with File Based cache&lt;/b&gt;
      &lt;br /&gt;
      &lt;b&gt;Without the "dirt cheap trick"&lt;/b&gt;
      &lt;br /&gt;
      &lt;table&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transactions:     
            &lt;/td&gt;
            &lt;td&gt;                324 hits&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Availability:     
            &lt;/td&gt;
            &lt;td&gt;             100.00 %&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Elapsed time:       
            &lt;/td&gt;
            &lt;td&gt;            59.94 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Data transferred:   
            &lt;/td&gt;
            &lt;td&gt;             2.13 MB&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Response time:       
            &lt;/td&gt;
            &lt;td&gt;            0.92 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transaction rate:    
            &lt;/td&gt;
            &lt;td&gt;            5.41 trans/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Throughput:          
            &lt;/td&gt;
            &lt;td&gt;            0.04 MB/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Concurrency:          
            &lt;/td&gt;
            &lt;td&gt;           4.95&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Successful transactions:  
            &lt;/td&gt;
            &lt;td&gt;        324&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Failed transactions:      
            &lt;/td&gt;
            &lt;td&gt;          0&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Longest transaction:     
            &lt;/td&gt;
            &lt;td&gt;        2.32&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Shortest transaction:    
            &lt;/td&gt;
            &lt;td&gt;        0.63&lt;/td&gt;
         &lt;/tr&gt;
      &lt;/table&gt;
      &lt;br /&gt;
      &lt;b&gt;With the "dirt cheap trick"&lt;/b&gt;
      &lt;br /&gt;
      &lt;table&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transactions:        
            &lt;/td&gt;
            &lt;td&gt;              475 hits&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Availability:        
            &lt;/td&gt;
            &lt;td&gt;           100.00 %&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Elapsed time:        
            &lt;/td&gt;
            &lt;td&gt;            59.56 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Data transferred:    
            &lt;/td&gt;
            &lt;td&gt;             3.14 MB&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Response time:       
            &lt;/td&gt;
            &lt;td&gt;             0.62 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transaction rate:     
            &lt;/td&gt;
            &lt;td&gt;            7.98 trans/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Throughput:          
            &lt;/td&gt;
            &lt;td&gt;             0.05 MB/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Concurrency:          
            &lt;/td&gt;
            &lt;td&gt;            4.97&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Successful transactions: 
            &lt;/td&gt;
            &lt;td&gt;          475&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Failed transactions:     
            &lt;/td&gt;
            &lt;td&gt;            0&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Longest transaction:     
            &lt;/td&gt;
            &lt;td&gt;         1.45&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Shortest transaction:    
            &lt;/td&gt;
            &lt;td&gt;         0.37&lt;/td&gt;
         &lt;/tr&gt;
      &lt;/table&gt;
      &lt;br /&gt;
      &lt;b&gt;Examples with memcache&lt;/b&gt;
      &lt;br /&gt;
      &lt;b&gt;Without the "dirt cheap trick"&lt;/b&gt;
      &lt;br /&gt;
      &lt;table&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transactions:    
            &lt;/td&gt;
            &lt;td&gt;                  329 hits&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Availability:     
            &lt;/td&gt;
            &lt;td&gt;              100.00 %&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Elapsed time:      
            &lt;/td&gt;
            &lt;td&gt;              59.65 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Data transferred:  
            &lt;/td&gt;
            &lt;td&gt;               2.17 MB&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Response time:     
            &lt;/td&gt;
            &lt;td&gt;               0.90 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transaction rate:   
            &lt;/td&gt;
            &lt;td&gt;              5.52 trans/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Throughput:         
            &lt;/td&gt;
            &lt;td&gt;              0.04 MB/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Concurrency:       
            &lt;/td&gt;
            &lt;td&gt;               4.95&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Successful transactions:
            &lt;/td&gt;
            &lt;td&gt;           329&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Failed transactions:    
            &lt;/td&gt;
            &lt;td&gt;             0&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Longest transaction:   
            &lt;/td&gt;
            &lt;td&gt;           1.60&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Shortest transaction:    
            &lt;/td&gt;
            &lt;td&gt;         0.68&lt;/td&gt;
         &lt;/tr&gt;
      &lt;/table&gt;
      &lt;br /&gt;
      &lt;b&gt;With the "dirt cheap trick"&lt;/b&gt;
      &lt;br /&gt;
      &lt;table&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transactions:
            &lt;/td&gt;
            &lt;td&gt;                    507 hits&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Availability: 
            &lt;/td&gt;
            &lt;td&gt;                     100.00 %&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Elapsed time:   
            &lt;/td&gt;
            &lt;td&gt;               59.47 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Data transferred: 
            &lt;/td&gt;
            &lt;td&gt;              3.35 MB&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Response time:    
            &lt;/td&gt;
            &lt;td&gt;              0.58 secs&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Transaction rate:  
            &lt;/td&gt;
            &lt;td&gt;             8.53 trans/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Throughput:          
            &lt;/td&gt;
            &lt;td&gt;           0.06 MB/sec&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Concurrency:         
            &lt;/td&gt;
            &lt;td&gt;           4.97&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Successful transactions:
            &lt;/td&gt;
            &lt;td&gt;         507&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Failed transactions:     
            &lt;/td&gt;
            &lt;td&gt;          0&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Longest transaction:    
            &lt;/td&gt;
            &lt;td&gt;        1.91&lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               Shortest transaction:    
            &lt;/td&gt;
            &lt;td&gt;       0.40&lt;/td&gt;
         &lt;/tr&gt;
      &lt;/table&gt;
      &lt;br /&gt;
      Pretty awesome right?
      Don't think siege is a good testing tool and this is not  a good indication? What about jmeter?
      &lt;br /&gt;
      Here is the test plan I used:
      &lt;br /&gt;
      &lt;pre class="brush: xml&gt;
      &lt;?xml version="1.0" encoding="UTF-8"?&gt;
      &lt;jmeterTestPlan version="1.2" properties="2.1"&gt;
         &lt;hashTree&gt;
            &lt;TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true"&gt;
               &lt;stringProp name="TestPlan.comments"&gt;&lt;/stringProp&gt;
               &lt;boolProp name="TestPlan.functional_mode"&gt;false&lt;/boolProp&gt;
               &lt;boolProp name="TestPlan.serialize_threadgroups"&gt;false&lt;/boolProp&gt;
               &lt;elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"&gt;
                  &lt;collectionProp name="Arguments.arguments" /&gt;
               &lt;/elementProp&gt;
               &lt;stringProp name="TestPlan.user_define_classpath"&gt;&lt;/stringProp&gt;
            &lt;/TestPlan&gt;
            &lt;hashTree&gt;
               &lt;ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true"&gt;
                  &lt;elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"&gt;
                     &lt;boolProp name="LoopController.continue_forever"&gt;false&lt;/boolProp&gt;
                     &lt;stringProp name="LoopController.loops"&gt;1&lt;/stringProp&gt;
                  &lt;/elementProp&gt;
                  &lt;stringProp name="ThreadGroup.num_threads"&gt;10&lt;/stringProp&gt;
                  &lt;stringProp name="ThreadGroup.ramp_time"&gt;1&lt;/stringProp&gt;
                  &lt;longProp name="ThreadGroup.start_time"&gt;1340804136000&lt;/longProp&gt;
                  &lt;longProp name="ThreadGroup.end_time"&gt;1340804136000&lt;/longProp&gt;
                  &lt;boolProp name="ThreadGroup.scheduler"&gt;false&lt;/boolProp&gt;
                  &lt;stringProp name="ThreadGroup.on_sample_error"&gt;continue&lt;/stringProp&gt;
                  &lt;stringProp name="ThreadGroup.duration"&gt;&lt;/stringProp&gt;
                  &lt;stringProp name="ThreadGroup.delay"&gt;&lt;/stringProp&gt;
               &lt;/ThreadGroup&gt;
               &lt;hashTree&gt;
                  &lt;HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="/apparel" enabled="true"&gt;
                     &lt;elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"&gt;
                        &lt;collectionProp name="Arguments.arguments" /&gt;
                     &lt;/elementProp&gt;
                     &lt;stringProp name="HTTPSampler.domain"&gt;mage.dev&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.port"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.connect_timeout"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.response_timeout"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.protocol"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.contentEncoding"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.path"&gt;/apparel&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.method"&gt;GET&lt;/stringProp&gt;
                     &lt;boolProp name="HTTPSampler.follow_redirects"&gt;false&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.auto_redirects"&gt;true&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.use_keepalive"&gt;true&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.DO_MULTIPART_POST"&gt;false&lt;/boolProp&gt;
                     &lt;stringProp name="HTTPSampler.FILE_NAME"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.FILE_FIELD"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.mimetype"&gt;&lt;/stringProp&gt;
                     &lt;boolProp name="HTTPSampler.monitor"&gt;false&lt;/boolProp&gt;
                     &lt;stringProp name="HTTPSampler.embedded_url_re"&gt;&lt;/stringProp&gt;
                  &lt;/HTTPSampler&gt;
                  &lt;hashTree&gt;
                     &lt;HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"&gt;
                        &lt;collectionProp name="HeaderManager.headers"&gt;
                           &lt;elementProp name="Accept-Language" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept-Language&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;en-us,en;q=0.5&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="Accept" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="User-Agent" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;User-Agent&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="Accept-Encoding" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept-Encoding&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;gzip, deflate&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                        &lt;/collectionProp&gt;
                     &lt;/HeaderManager&gt;
                     &lt;hashTree /&gt;
                  &lt;/hashTree&gt;
                  &lt;HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="/furniture/living-room" enabled="true"&gt;
                     &lt;elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"&gt;
                        &lt;collectionProp name="Arguments.arguments" /&gt;
                     &lt;/elementProp&gt;
                     &lt;stringProp name="HTTPSampler.domain"&gt;mage.dev&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.port"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.connect_timeout"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.response_timeout"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.protocol"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.contentEncoding"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.path"&gt;/furniture/living-room&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.method"&gt;GET&lt;/stringProp&gt;
                     &lt;boolProp name="HTTPSampler.follow_redirects"&gt;false&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.auto_redirects"&gt;true&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.use_keepalive"&gt;true&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.DO_MULTIPART_POST"&gt;false&lt;/boolProp&gt;
                     &lt;stringProp name="HTTPSampler.FILE_NAME"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.FILE_FIELD"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.mimetype"&gt;&lt;/stringProp&gt;
                     &lt;boolProp name="HTTPSampler.monitor"&gt;false&lt;/boolProp&gt;
                     &lt;stringProp name="HTTPSampler.embedded_url_re"&gt;&lt;/stringProp&gt;
                  &lt;/HTTPSampler&gt;
                  &lt;hashTree&gt;
                     &lt;HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"&gt;
                        &lt;collectionProp name="HeaderManager.headers"&gt;
                           &lt;elementProp name="Accept-Language" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept-Language&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;en-us,en;q=0.5&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="Accept" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="User-Agent" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;User-Agent&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="Accept-Encoding" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept-Encoding&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;gzip, deflate&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                        &lt;/collectionProp&gt;
                     &lt;/HeaderManager&gt;
                     &lt;hashTree /&gt;
                  &lt;/hashTree&gt;
                  &lt;HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="/furniture/bedroom" enabled="true"&gt;
                     &lt;elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"&gt;
                        &lt;collectionProp name="Arguments.arguments" /&gt;
                     &lt;/elementProp&gt;
                     &lt;stringProp name="HTTPSampler.domain"&gt;mage.dev&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.port"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.connect_timeout"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.response_timeout"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.protocol"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.contentEncoding"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.path"&gt;/furniture/bedroom&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.method"&gt;GET&lt;/stringProp&gt;
                     &lt;boolProp name="HTTPSampler.follow_redirects"&gt;false&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.auto_redirects"&gt;true&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.use_keepalive"&gt;true&lt;/boolProp&gt;
                     &lt;boolProp name="HTTPSampler.DO_MULTIPART_POST"&gt;false&lt;/boolProp&gt;
                     &lt;stringProp name="HTTPSampler.FILE_NAME"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.FILE_FIELD"&gt;&lt;/stringProp&gt;
                     &lt;stringProp name="HTTPSampler.mimetype"&gt;&lt;/stringProp&gt;
                     &lt;boolProp name="HTTPSampler.monitor"&gt;false&lt;/boolProp&gt;
                     &lt;stringProp name="HTTPSampler.embedded_url_re"&gt;&lt;/stringProp&gt;
                  &lt;/HTTPSampler&gt;
                  &lt;hashTree&gt;
                     &lt;HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"&gt;
                        &lt;collectionProp name="HeaderManager.headers"&gt;
                           &lt;elementProp name="Accept-Language" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept-Language&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;en-us,en;q=0.5&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="Accept" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="User-Agent" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;User-Agent&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                           &lt;elementProp name="Accept-Encoding" elementType="Header"&gt;
                              &lt;stringProp name="Header.name"&gt;Accept-Encoding&lt;/stringProp&gt;
                              &lt;stringProp name="Header.value"&gt;gzip, deflate&lt;/stringProp&gt;
                           &lt;/elementProp&gt;
                        &lt;/collectionProp&gt;
                     &lt;/HeaderManager&gt;
                     &lt;hashTree /&gt;
                  &lt;/hashTree&gt;
               &lt;/hashTree&gt;
               &lt;ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true"&gt;
                  &lt;boolProp name="ResultCollector.error_logging"&gt;false&lt;/boolProp&gt;
                  &lt;objProp&gt;
                     &lt;name&gt;saveConfig&lt;/name&gt;
                     &lt;value class="SampleSaveConfiguration"&gt;
                        &lt;time&gt;true&lt;/time&gt;
                        &lt;latency&gt;true&lt;/latency&gt;
                        &lt;timestamp&gt;true&lt;/timestamp&gt;
                        &lt;success&gt;true&lt;/success&gt;
                        &lt;label&gt;true&lt;/label&gt;
                        &lt;code&gt;true&lt;/code&gt;
                        &lt;message&gt;true&lt;/message&gt;
                        &lt;threadName&gt;true&lt;/threadName&gt;
                        &lt;dataType&gt;true&lt;/dataType&gt;
                        &lt;encoding&gt;false&lt;/encoding&gt;
                        &lt;assertions&gt;true&lt;/assertions&gt;
                        &lt;subresults&gt;true&lt;/subresults&gt;
                        &lt;responseData&gt;false&lt;/responseData&gt;
                        &lt;samplerData&gt;false&lt;/samplerData&gt;
                        &lt;xml&gt;true&lt;/xml&gt;
                        &lt;fieldNames&gt;false&lt;/fieldNames&gt;
                        &lt;responseHeaders&gt;false&lt;/responseHeaders&gt;
                        &lt;requestHeaders&gt;false&lt;/requestHeaders&gt;
                        &lt;responseDataOnError&gt;false&lt;/responseDataOnError&gt;
                        &lt;saveAssertionResultsFailureMessage&gt;false&lt;/saveAssertionResultsFailureMessage&gt;
                        &lt;assertionsResultsToSave&gt;0&lt;/assertionsResultsToSave&gt;
                        &lt;bytes&gt;true&lt;/bytes&gt;
                     &lt;/value&gt;
                  &lt;/objProp&gt;
                  &lt;stringProp name="filename"&gt;&lt;/stringProp&gt;
               &lt;/ResultCollector&gt;
               &lt;hashTree /&gt;
            &lt;/hashTree&gt;
         &lt;/hashTree&gt;
      &lt;/jmeterTestPlan&gt;
      &lt;/pre&gt;
      &lt;p&gt;Here are the results, sorry about the formatting:&lt;/p&gt;
      &lt;br /&gt;
      &lt;b&gt;Without the "dirt cheap trick"&lt;/b&gt;
      &lt;br /&gt;
      &lt;table&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;sampler_label&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_count&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;average&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_min&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_max&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_stddev&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_error%&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_rate&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_bandwidth&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;average_bytes&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;/apparel&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;10&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;1710&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;1274&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;2180&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;290.2423125597&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;4.5724737083&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;199.8358553384&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;44753&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;/furniture/living-room&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;10&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;896&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;618&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;1272&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;254.8664159908&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;7.5757575758&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;227.1173650568&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;30699&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;/furniture/bedroom&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;10&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;747&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;565&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;953&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;137.6&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;7.3637702504&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;204.8623895434&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;28488&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;TOTAL&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;30&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;1117&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;565&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;2180&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;484.8805133455&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;7.2904009721&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;246.6680589307&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;34646.6666666667&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
      &lt;/table&gt;
      &lt;br /&gt;
      &lt;b&gt;With the "dirt cheap trick"&lt;/b&gt;
      &lt;br /&gt;
      &lt;table&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;sampler_label&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_count&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;average&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_min&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_max&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_stddev&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_error%&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_rate&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;aggregate_report_bandwidth&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;average_bytes&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;/apparel&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;10&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;675&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;434&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;904&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;147.3737086457&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;6.1199510404&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;268.3156269125&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;44895&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;/furniture/living-room&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;10&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;741&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;581&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;950&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;107.7506844526&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;5.4436581383&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;164.0678160724&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;30862.6&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;/furniture/bedroom&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;10&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;631&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;389&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;827&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;157.5221889132&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;7.3691967576&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;206.1388863301&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;28644.4&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
         &lt;tr&gt;
            &lt;td&gt;
               &lt;p&gt;TOTAL&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;30&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;682&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;389&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;950&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;146.3524057427&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;0&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;10.8577633008&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;369.0013685306&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
               &lt;p&gt;34800.6666666667&lt;/p&gt;
            &lt;/td&gt;
         &lt;/tr&gt;
      &lt;/table&gt;
      &lt;br /&gt;
      As you can see this is trick helps a lot but it doesn't compete with Magento's FPC or Varnish and it still needs lots of polishing. The good think is that is doesn't require holepunching or lots of Magento knowledge.
      Now a few pointers... this is not the full implementation, as this code doesn't work with load balancers and there is not a way to clear it here. But implementing both is trivial.
   &lt;/span&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/07/dirt-cheap-way-to-make-magento-fly.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-6282954101315922409</guid><pubDate>Thu, 26 Jul 2012 22:06:00 +0000</pubDate><atom:updated>2012-07-26T18:08:54.643-04:00</atom:updated><title>PHP Offloading... Nginx helps so much!</title><description>&lt;span class="fullpost"&gt;
So let's continue our attempt to improve Magento's performance and this time around let's focus on the web server itself.&lt;br /&gt;

There are a bunch of &lt;a href="http://en.wikipedia.org/wiki/Web_server" target="_blank"&gt;web servers&lt;/a&gt; out there but the most known are, a least to me: &lt;a href="http://www.apache.org/" target="_blank"&gt;Apache&lt;/a&gt;, &lt;a href="http://www.nginx.org/" target="_blank"&gt;Nginx&lt;/a&gt; and &lt;a href="http://www.lighttpd.net/" target="_blank"&gt;Lighttpd&lt;/a&gt;&lt;br /&gt;

My favorite, and of course I am biased here, is Nginx and it approach to serving content. As you may all know Nginx is an event-based web server and the main advantage of this asynchronous approach is scalability.&amp;nbsp;&lt;br /&gt;

Because at the end of the day what we are going to have is a complete static page (after it has been cached once) being served from the web server.&lt;br /&gt;&lt;br /&gt;

Apache is out of the question because nginx is faster at serving static files and consumes much less memory for concurrent requests. As Nginx is event-based it doesn't need to spawn new processes or threads for each request, so its memory usage is very low and that is the key.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;

We could use lighttpd (it's even more compatible with apache) but the cpu and memory fingerprint is bigger than nginx and we are all about performance aren't we?
&lt;br /&gt;&lt;br /&gt;

So here are my recommended configurations for both Nginx and fast-cgi, of course suggestions are welcome:&lt;br /&gt;

&lt;pre class="brush: c"&gt;
server {
    listen 80 default;
    listen 443 default ssl;
    ssl_certificate /etc/pki/tls/certs/2014-www.example.com.pem;
    ssl_certificate_key /etc/pki/tls/certs/2014-www.example.com.pem;
    server_name www.example.com example.com; ## Domain is here twice so server_name_in_redirect will favour the www
    root /var/www/vhosts/example.com;
 
    location / {
        index index.html index.php;
        try_files $uri $uri/ @handler; 
        expires 30d; ## Assume all files are cachable
    }
 
    ## These locations would be hidden by .htaccess normally
    location /app/                { deny all; }
    location /includes/           { deny all; }
    location /lib/                { deny all; }
    location /media/downloadable/ { deny all; }
    location /pkginfo/            { deny all; }
    location /report/config.xml   { deny all; }
    location /var/                { deny all; }
 
#    location /var/export/ { 
#        auth_basic           "Restricted"; ## Message shown in login window
#        auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword
#        autoindex            on;
#    }
 
    location  /. { ## Disable .htaccess and other hidden files
        return 404;
    }
 
    location @handler { ## Magento uses a common front handler
        rewrite / /index.php;
    }
 
    location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
        rewrite ^(.*.php)/ $1 last;
    }
 
    location ~ .php$ { ## Execute PHP scripts
        if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
 
        expires        off; ## Do not cache dynamic content
 fastcgi_read_timeout 120;
 fastcgi_buffer_size 128k;
 fastcgi_buffers 4 256k;
 fastcgi_busy_buffers_size 256k;
        fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_param  HTTPS $fastcgi_https;
        fastcgi_param  PHP_VALUE "memory_limit = 341M";
 fastcgi_param  PHP_VALUE "max_execution_time = 18000";
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  MAGE_RUN_CODE default; ## Store code is defined in administration &gt; Configuration &gt; Manage Stores
        fastcgi_param  MAGE_RUN_TYPE store;
        #fastcgi_param  MAGE_IS_DEVELOPER_MODE true; //enable developer mode?
        include        fastcgi_params; ## See /etc/nginx/fastcgi_params
    }
}
&lt;/pre&gt;
&lt;pre class="brush: c"&gt;
; Start a new pool named 'www'.
[www]

listen = /var/run/php-fpm/php-fpm.sock
user = apache
group = apache
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 50
pm.max_requests = 500

pm.status_path = /phpfpm-status
request_terminate_timeout = 5m
request_slowlog_timeout = 2m
slowlog = /var/log/php-fpm/www-slow.log

php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on

&lt;/pre&gt;

Contents of /etc/nginx/fastcgi_params
&lt;pre class="brush: c"&gt;

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
&lt;/pre&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/07/php-offloading-nginx-helps-so-much.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-1791084176141723564</guid><pubDate>Wed, 25 Jul 2012 02:19:00 +0000</pubDate><atom:updated>2012-07-26T18:09:21.319-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Magento</category><category domain="http://www.blogger.com/atom/ns#">performance</category><category domain="http://www.blogger.com/atom/ns#">System Administration</category><category domain="http://www.blogger.com/atom/ns#">Varnish</category><title>PHP offloading for better performance</title><description>&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;So you recently launched your PHP application (read &lt;a href="http://www.magentocommerce.com/"&gt;Magento&lt;/a&gt;) just to realize that it is really slow even though you have state of the art hardware, software and it is configured to kick ass. You decided to install &lt;a href="https://www.varnish-cache.org/"&gt;varnish&lt;/a&gt; to help full page caching and your CDN, which it only has gzipped merged and minified assets,  to serve content faster now your site seems to be flying but &lt;a href="http://newrelic.com/"&gt;New Relic&lt;/a&gt; still reveals so many bottlenecks specially for the fillers you needed to keep some dynamic content rocking.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;You decide to run promotion that would bring 20K plus customers and decided to add more servers, virtual machines and the cloud can be so awesome. Soon to realize that your site is now really slow specially when checking out and some time later your site is DOWN!!! WHY!?!!!&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;Because your reverse proxy is not serving all of the customers let alone is not serving the whole content from cache as it has to fetch some from the server, more on this later. So believe it or not, your server is still getting hammered and might be even worse than before.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white;"&gt;&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;Reverse proxies are really awesome but if applied to a inefficient application, it will come back to hunt you and be your worst nightmare.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white;"&gt;&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;Caching is supposed to be good but nowadays it has become the best way to hide all of the snafus and foobars in the application. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white;"&gt;&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;So what is the problem? For once almost everyone does development one way through the programming language they know and rarely, if any, venture or dare to think of a possible world outside of that realm. Aside from the copy paste dogma of course.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;One problem is that most people tend to try to keep the dynamic content in the page through a hybrid combination of fresh content (retrieved from the server) and cached content. Most caching systems have developed sophisticated algorithm to make it work which adds a new layer of complexity.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;Let's go back to your PHP application, one of the areas that usually needs to be hole-punched is the header because it contains the cart widget, the account (log-in or out) and wishlist links. But do we really need to hole-punched it? Nop!&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;b&gt;PHP offloading is a very useful technique to improve performance&lt;/b&gt;, it refers to efficently distribute the workload among all the servers or other programming languages in the sytem. Also known as Operation Driven Development (ODD) where the type of operation dictates in which server or programming language the task it will take place. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;So let's take the cart widget and see how we could do it without having to even think about hole-punching:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;Every time an operation that involves the cart object takes place, this one gets saved. This means when you remove, add or update an item in your shopping cart you get this event &lt;/span&gt;&lt;span style="background-color: white; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;b&gt;checkout_cart_save_after &lt;/b&gt;so why don't we create a cookie that contains off all the items information?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;Snippets below, I assume you do Magento development:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;In your module etc/config.xml add:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush: xml"&gt; &lt;frontend&gt;
        &lt;events&gt;
            &lt;checkout_cart_save_after&gt;
                &lt;observers&gt;
                    &lt;po_checkout_cart_save_after&gt;
                        &lt;class&gt;phpoffloading/observer&lt;/class&gt;
                        &lt;method&gt;cartUpdate&lt;/method&gt;
                    &lt;/po_checkout_cart_save_after&gt;
                &lt;/observers&gt;
            &lt;/checkout_cart_save_after&gt;
        &lt;/events&gt;
        &lt;layout&gt;
            &lt;updates&gt;
                &lt;phpoffloading module="Php_Offloading"&gt;
                    &lt;file&gt;phpoffloading.xml&lt;/file&gt;
                
            &lt;/phpoffloading&gt;&lt;/updates&gt;
        &lt;/layout&gt;
    &lt;/frontend&gt;
&lt;/pre&gt;
Replace phpoffloading with the name of your model class.&lt;br /&gt;
Now in your observer add:
&lt;br /&gt;
&lt;pre class="brush: php"&gt;    /**
     * Process all the cart / quote updates to ensure we update the cookie correctly
     * @param type $observer 
     */
    public function cartUpdate($observer) {
        // using singleton instead of the event to use the same function for different events
        $cart = Mage::getSingleton('checkout/cart');
        $quote = $cart-&amp;gt;getQuote();

        /**
         * @var $totals needed for the subtotal 
         */
        $totals = $quote-&amp;gt;getTotals();
        /**
         * @var $checkouthelper used for translation and price formatting 
         */
        $checkoutHelper = Mage::helper('checkout');
        $items = (int) $cart-&amp;gt;getSummaryQty();
        if ($items &amp;gt; 0) {
            $cartInfo = array(
                'subtotal' =&amp;gt; $checkoutHelper-&amp;gt;formatPrice($totals['subtotal']-&amp;gt;getValue()),
                'items' =&amp;gt; $items,
                'itemsmsg' =&amp;gt; $items == 1 ? "item" : "items",
                'viewcart' =&amp;gt; $checkoutHelper-&amp;gt;__('View Cart')
            );
            $cartInfo = json_encode($cartInfo);
             $this-&amp;gt;setCookie('cart_cookie', $cartInfo);
        } else {
            $this-&amp;gt;deleteCartCookie();
        }
        return $this;
    }
&lt;/pre&gt;
In your template:&lt;span style="background-color: white;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;pre class="brush: html"&gt;&lt;div id="template_container"&gt;
&lt;div class="top-cart"&gt;
&lt;div id="cart_items_container"&gt;
&lt;div class="cart-contents"&gt;
&lt;/div&gt;
&lt;div class="cart-action"&gt;
&lt;button class="button" onclick="setLocation('&amp;lt;?php echo $this-&amp;gt;getUrl('checkout/cart'); ?&amp;gt;')" type="button"&gt;&lt;span id="viewcart"&gt;&lt;/span&gt;&lt;/button&gt;
            &lt;/div&gt;
&lt;/div&gt;
&lt;div class="empty" id="empty_message"&gt;
You have no items in your cart.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/pre&gt;
You can have this javascript either on the same template or add it as an external file:
&lt;br /&gt;
&lt;pre class="brush: javascript"&gt;&lt;script type="text/javascript"&gt;
    //set the variables
    var cartCookie = Mage.Cookies.get('cart_cookie') 
    var emptyMessage = $("empty_message")
    var cartContainer = $("cart_items_container")
    
    if (!cartCookie){
        emptyMessage.show()
        cartContainer.hide()
    }
    else{
        //parse the json response, is this the fastest way?
        cartCookie = cartCookie.evalJSON(true);
        
        //update the html
        $('cart_total').update(cartCookie.subtotal)
        $('viewcart').update(cartCookie.viewcart.replace("+"," "))
        $('cart_amount').update(cartCookie.items +" " + cartCookie.itemsmsg + ":")
        emptyMessage.hide()
        cartContainer.show()
    }    
&lt;/script&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style="background-color: white; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;Every time a page gets loaded now instead of going to the server the content will remain in the browser and you don't need to request content from the server again. This is a very small change how much improvement do I get? Say you go from 750ms to 2ms in the server response time what would you say?&amp;nbsp;This is because varnish 1-) doesn't need to understand what ESI is and 2-) all of the content is served from cache. This doesn't apply solely to varnish but to Magento's own full page caching solution. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white; color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;This approach works fine for: wishlist, logged in/out but it doesn't work quite well with recently viewed items. For that we'll do a follow up article.&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: #474747; font-family: 'Helvetica Neue', Arial, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 18px; white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;script src="http://crux-framework-tools.googlecode.com/svn/trunk/misc/highlight/highlightLoader.js"&gt; &lt;/script&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/07/php-offloading-for-better-performance.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-5617424597460879245</guid><pubDate>Mon, 23 Jul 2012 17:55:00 +0000</pubDate><atom:updated>2012-07-23T13:55:58.484-04:00</atom:updated><title>FireFox vs Virtualized environments</title><description>&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
Firefox rocks no doubt about it... but using more memory than virtualbox just to run magento is not cool at all! &lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
This is why I really dislike using FireFox and love using &lt;a href="http://getswiftfox.com/"&gt;SwiftFox&lt;/a&gt;. How come Firefox is taking 2GB of ram, that is as much as my virtualized Ubuntu Desktop and more than my virtualized ubuntu server. In other words with that much memory I could be running a few more computers.&lt;/div&gt;
&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghpQ-CMdPpbNSi56LJr5940O-2y73kN41CrhWzAM8Z2nM5yD_vClNBlyi9JGWCRh7bV32z55E4wZsHW2oD7UYNymvOQo3__ZzGAUZM7hq0kryIPE6_9QkI55sAfLetDJdJY8hwFFdrFSg/s1600/Selection_013.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghpQ-CMdPpbNSi56LJr5940O-2y73kN41CrhWzAM8Z2nM5yD_vClNBlyi9JGWCRh7bV32z55E4wZsHW2oD7UYNymvOQo3__ZzGAUZM7hq0kryIPE6_9QkI55sAfLetDJdJY8hwFFdrFSg/s320/Selection_013.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: justify;"&gt;
Swiftfox is a highly optimized firefox which aims to be lightweight 
while still being robust, powerful and most importantly, compatible with
 all of the FifeFox addons.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/07/firefox-vs-virtualized-environments.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghpQ-CMdPpbNSi56LJr5940O-2y73kN41CrhWzAM8Z2nM5yD_vClNBlyi9JGWCRh7bV32z55E4wZsHW2oD7UYNymvOQo3__ZzGAUZM7hq0kryIPE6_9QkI55sAfLetDJdJY8hwFFdrFSg/s72-c/Selection_013.png" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-465233464155179968</guid><pubDate>Thu, 19 Jul 2012 05:55:00 +0000</pubDate><atom:updated>2012-07-19T01:55:06.696-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Bash</category><category domain="http://www.blogger.com/atom/ns#">System Administration</category><category domain="http://www.blogger.com/atom/ns#">Ubuntu</category><title>Restore Ubuntu to the default settings without re-installing it</title><description>As a web developer (read app freak) I am always installing new IDEs, media players and libraries to try out. This madness cycle can definitely take a toll on your computer and slow it down to the point of no return.&lt;br /&gt;
&lt;br /&gt;
Usually that is when you'd decide to format the computer and start anew. So when my wireless network was experiencing some hiccups and my computer will crash every 2 seconds for no reason or worse when it started using all of the swap memory I knew it was time to wipe it clean. Then I look at my home folder and I have over 300GB of data and I am kind of lazy. That is when I think to myself, no problem the home folder is in its own partition, right? Nope. It is not *BUMMER*&lt;br /&gt;
&lt;br /&gt;
I don't want to&amp;nbsp;re-install&amp;nbsp;and reconfigure all of the programs I use but don't want to restart my computer every hour or so - that is when I remembered that some bash commands could save my day.&lt;br /&gt;
&lt;br /&gt;
Currently I am using ubuntu 12.04 and I want to restore it to be the same it was when I first installed it, sure no problem let's start by getting two simple files from the ISO file (you still have the iso file right?):&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;casper/filesystem.manifest&lt;/span&gt;&lt;br /&gt;
casper/filesystem.manifest-remove&lt;br /&gt;
&lt;br /&gt;
or just casper/&lt;span style="background-color: white;"&gt;filesystem.manifest-desktop for *buntu 11.10 or earlier&lt;/span&gt;&lt;br /&gt;
Now let's combine these 2 files:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;comm -3 &amp;lt;(cat filesystem.manifest | awk '{print $1}' | sort) &amp;lt;(cat filesystem.manifest-remove | sort) &amp;gt; default.txt
&lt;/pre&gt;
&lt;br /&gt;
If you have Ubuntu 11.10 or earlier then to get the default.txt file do:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;cat filesystem.manifest-desktop | awk '{print $1}' | sort &amp;gt; default.txt
&lt;/pre&gt;
default.txt contains a sorted list of all the programs our default installation should include.

Now let's get the software currently installed in our computer:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;dpkg --get-selections | awk '{print $1}' | sort &amp;gt; currently_installed.txt
&lt;/pre&gt;
&lt;pre class="brush: c"&gt;
&lt;/pre&gt;
If we diff the default software vs what is currently installed, we can get what was added:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt; diff -u default.txt currently_installed.txt | grep "^+[^+]" | cut -c 2- &amp;gt; additions.txt
&lt;/pre&gt;
or what was removed:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;diff -u default.txt currently_installed.txt | grep "^-[^-]" | cut -c 2- &amp;gt; removed.txt
&lt;/pre&gt;
Now if we want to remove all of the additions, including the configuration files:

&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;sudo apt-get purge $(cat additions.txt)
&lt;/pre&gt;

To add back the files we removed:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;sudo apt-get install $(cat removed.txt)
&lt;/pre&gt;
&lt;pre class="brush: c"&gt;
&lt;/pre&gt;
Remove the configuration files:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: c"&gt;rm -rf .gnome .gnome2 .gconf .gconfd .metacity
&lt;/pre&gt;
That should bring your current ubuntu based to the default state (I believe it should work with every Linux Distro, but the judge is still out there).&lt;br /&gt;
&lt;br /&gt;
This is a bit radical though, before removing any files make sure that you only remove anything that you don't want to keep. And just in case, make a backup of your files just in case.&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/07/restore-ubuntu-to-default-settings.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-5476387922419250704</guid><pubDate>Tue, 17 Jul 2012 04:30:00 +0000</pubDate><atom:updated>2012-07-17T00:30:17.412-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Magento</category><category domain="http://www.blogger.com/atom/ns#">Varnish</category><title>Varnish implementation hints and good to know</title><description>Sharing knowledge is always a good idea. Lately I have been doing lots of integration with Varnish and Magento with different clients and it will be interesting to find out if you have any ideas or suggestions (read improvements) to make it better and ultimately help the community even more:

&lt;h2&gt;&lt;b2&gt;Setting up varnish in switch mode:&lt;/b2&gt;&lt;/h2&gt;

In my home directory I always have a bash aliases (vim ~/.bash_aliases) file where I add the following iptable rules:
&lt;pre class="brush: c"&gt;
alias ipforward='sysctl net.ipv4.ip_forward=1'
alias varnishon='iptables -t nat  -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8888'
alias varnishmasq='iptables -t nat -A POSTROUTING -j MASQUERADE'
alias varnishoff='iptables -t nat -D PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8888'
alias varnishstatus='iptables -L -t nat | grep -q 8888; if [ "test$?" = "test0" ]; then echo "Varnish On"; else echo "Varnish Off"; fi'
&lt;/pre&gt;
This allows me to switch varnish on and off without changing the existing architecture. The best thing about this is that if something were to go wrong I can immediately turn varnish off and test the web server alone. Also internal routes won't go through varnish which let's me test side by side the pages and speeds.

&lt;h2&gt;&lt;b2&gt;Setting up a varnish on flag:&lt;/b2&gt;&lt;/h2&gt;

When Implementing ESI, always set a variable to tell you whether varnish is on or not.

For instance on my varnish configuration file (/etc/varnish/default.vcl), at the very end I have:
&lt;pre class="brush: c"&gt;   
/**
   * Set a flag for web store to check if varnish is on or not
   * Very important when doing switch on / off installations with ESI  
  **/

 set req.http.X-Varnish-On = 1;
&lt;/pre&gt;
&lt;pre class="brush: php"&gt;
    if (isset($_SERVER['HTTP_X_VARNISH_ON'])): 
           &lt;!--esi &lt;esi:include src="&lt;?php echo $this-&gt;getEsiUrl() " /&gt;--&gt;
    else: 
           &lt;?php  echo $this-&gt;getNormalContent() ?&gt;
   endif;
&lt;/pre&gt;
 I have it a the very because, all of the whitelist and passes have already been checked – so I am assure that the only pages left are “varnished” pages.

&lt;h2&gt;&lt;b2&gt;Remove all the cookies&lt;/b2&gt;&lt;/h2&gt;

The only cookie value Magento requires is the frontend cookie:
&lt;pre class="brush: c"&gt;
//check that the cookie is still set
if (req.http.Cookie){

 set req.http.X-Cookie = ";" +req.http.Cookie;
 set req.http.X-Cookie = regsuball(req.http.X-Cookie, "; +", ";");
 set req.http.X-Cookie = regsuball(req.http.X-Cookie, ";(frontend)=", "; \1=");
 set req.http.X-Cookie = regsuball(req.http.X-Cookie, ";[^ ][^;]*", "");
 set req.http.X-Cookie = regsuball(req.http.X-Cookie, "^[; ]+|[; ]+$", "");
}

// Remove cookies
unset req.http.Cookie;
&lt;/pre&gt;
Then assuming you only have the x-cookie set for the frontend, in your php before the headers are sent:
&lt;pre class="brush: php"&gt;

$_frontend = isset ($_SERVER['HTTP_X_COOKIE']) ? $_SERVER['HTTP_X_COOKIE'] : null;
if ($_frontend){
    list ($name,$value) = explode("=",$_frontend);
    $_COOKIE[$name] = $value; //setCookie didn't work for me here
}
&lt;/pre&gt;

&lt;h2&gt;&lt;b2&gt;Clear Cms / Product / Category pages&lt;/b2&gt;&lt;/h2&gt;

Update the content frequently? When you save a cms page, product or category page simply hear the corresponding event and “purge” or “refresh” that URL. The important thing to remember is that if you can: 1-) use cURL in BASH over PHP's cURL and 2-) when clearing the product URLs you also need to clean the categories as well.

In the terminal you could do:
&lt;br &gt;
&lt;pre class="brush: c"&gt;
curl -X PURGE URL_TO_CLEAN
&lt;/pre&gt;

&lt;h2&gt;&lt;b2&gt;Clear / Refresh all pages&lt;/b2&gt;&lt;/h2&gt;

A favorite of mine – when finding all of the URLs in the system, use Magento's sitemap resource collections:
&lt;pre class="brush: php"&gt;
    //get all the url rewrites urls and cms pages (including the home page)
    public function getAllUrls() {

        $collections = array('sitemap/catalog_category', 'sitemap/catalog_product', 'sitemap/cms_page');

        $baseUrl = Mage::app()-&gt;getStore()-&gt;getBaseUrl();
        $storeId = Mage::app()-&gt;getStore()-&gt;getId();
        $urls = array();

        foreach ($collections as $collection) {
            $collection = Mage::getResourceModel($collection)-&gt;getCollection($storeId);
            $key = md5(serialize($collection));
            if ($data = $this-&gt;getDataFromCache($key)) {
                $urls = array_merge($urls, $data);
            } else {
                foreach ($collection as $url) {
                    $urls[] = htmlspecialchars($baseUrl . $url-&gt;getUrl());
                }
                $this-&gt;setKey($key)
                        -&gt;setData($urls)
                        -&gt;saveDataInCache();
            }
            unset($collection);
        }

        $urls = array_merge($urls, $this-&gt;getSearchUrls());
        //account for the homepage 
        $urls[] = $baseUrl;

        return $urls;
    }
     public function getSearchUrls() {
        $urls = array();
        $collection = Mage::getResourceModel('catalogsearch/query_collection')
                -&gt;setPopularQueryFilter(Mage::app()-&gt;getStore()-&gt;getId())
                -&gt;setOrder('popularity', 'DESC');

        $catalogSearchHelper = Mage::helper('catalogsearch');
        foreach ($collection as $search) {
            $urls[] = $catalogSearchHelper-&gt;getResultUrl($search-&gt;getData('name'));
        }

        return $urls;
    }
&lt;/pre&gt;
Please note that I use some extra functions here: setKey, setData, saveDataInCache &amp; getDataFromCache. Ultimately is all about performance and I rely on Magento's cache to save the collection of urls.

That will get you all of Magento URLs that your system might be caching. 

Now you could iterate that array and either refresh or purge varnish's cache&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/07/varnish-implementation-hints-and-good.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-1327123153195062709</guid><pubDate>Sun, 12 Feb 2012 06:07:00 +0000</pubDate><atom:updated>2012-02-12T01:07:35.080-05:00</atom:updated><title>Roma....</title><description>&lt;div&gt;&lt;p&gt;Roma tomato loves the water&lt;/p&gt;
&lt;br/&gt;&lt;img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipbWlTHnDzlGvGG80duzImUXFWzMBK-JoVY3Q4YZ_sJbrDNsPEJIjxrRYph3UpGcuu_vHWoYBnxDcxPeaYZyzqjQ-es5DOIBCtjYD2cs8IY7U0fK4t_PMggv-A__RwOInfFTC8tf9vqDw/' /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/02/roma.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipbWlTHnDzlGvGG80duzImUXFWzMBK-JoVY3Q4YZ_sJbrDNsPEJIjxrRYph3UpGcuu_vHWoYBnxDcxPeaYZyzqjQ-es5DOIBCtjYD2cs8IY7U0fK4t_PMggv-A__RwOInfFTC8tf9vqDw/s72-c" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-5853078761346043788</guid><pubDate>Tue, 24 Jan 2012 05:35:00 +0000</pubDate><atom:updated>2012-01-24T00:35:08.832-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">trip to iop</category><title>Trip to IOP</title><description>&lt;div&gt;&lt;p&gt;I hate Jellyfish &lt;/p&gt;
&lt;br/&gt;&lt;img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho2VjY-Ebgou-dvwBFuRXtHxkogFDkSlA2My3TIMJ13Djxm-UxAxKeXN9YLflAPkDnNY8QW0cCWGtIOdcv6ECY7A0iVXZ3orzuMNJNxJ8so9EpNDgI9hmSp3Hka098fE-G36Ztxx6TUBc/' /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2012/01/trip-to-iop.html</link><author>noreply@blogger.com (Anonymous)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho2VjY-Ebgou-dvwBFuRXtHxkogFDkSlA2My3TIMJ13Djxm-UxAxKeXN9YLflAPkDnNY8QW0cCWGtIOdcv6ECY7A0iVXZ3orzuMNJNxJ8so9EpNDgI9hmSp3Hka098fE-G36Ztxx6TUBc/s72-c" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-8840921756236592143</guid><pubDate>Fri, 11 Feb 2011 14:10:00 +0000</pubDate><atom:updated>2012-07-28T23:23:13.934-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Development</category><category domain="http://www.blogger.com/atom/ns#">Magento</category><category domain="http://www.blogger.com/atom/ns#">Web</category><category domain="http://www.blogger.com/atom/ns#">Zend Framework</category><title>Magento 301 Redirects</title><description>Did you ever want to create a redirect in a Magento Store without having to use htacess?&lt;br /&gt;
Using Observers and the powerful Request and Response objects from Zend Framework you can. In this example I will show how you can do it.&lt;br /&gt;
First you need to create the module, more on module creations here: http://goo.gl/vvT2j. &lt;br /&gt;
&lt;br /&gt;
Create a directory under app/code/community and name it FooBar, then create another directory under FooBar and name it Redirect. Create two directories inside FooBar: etc and Model.&lt;br /&gt;
Inside etc create a config.xml file and paste this into it:&lt;br /&gt;
Note: For some reason blogger keeps putting all tags in lowercase, foobar_redirect should be FooBar_Redirect.&lt;br /&gt;
&lt;span class="fullpost"&gt;&lt;br /&gt;
&lt;pre class="brush: xml"&gt;&lt;config&gt;
    &lt;modules&gt;
        &lt;FooBar_Redirect&gt;
            &lt;version&gt;0.1&lt;/version&gt;
        &lt;/FooBar_Redirect&gt;
    &lt;/modules&gt;
    &lt;global&gt;        
        &lt;models&gt;
            &lt;fooredirect&gt;
                &lt;class&gt;FooBar_Redirect_Model&lt;/class&gt;
            &lt;/fooredirect&gt;
        &lt;/models&gt;
        &lt;events&gt; 
            &lt;controller_action_predispatch&gt;
                &lt;observers&gt;
                    &lt;fooredirect&gt;
                        &lt;type&gt;singleton&lt;/type&gt;
                        &lt;class&gt;fooredirect/observer&lt;/class&gt;
                        &lt;method&gt;redirect&lt;/method&gt;
                    &lt;/fooredirect&gt;
                &lt;/observers&gt;
            &lt;/controller_action_predispatch&gt; 
        &lt;/events&gt;
    &lt;/global&gt;
&lt;/config&gt;
&lt;/pre&gt;&lt;br /&gt;
Now in the Model directory create the Observer.php file and paste this into it:&lt;br /&gt;
&lt;pre class="brush: php"&gt;class FooBar_Redirect_Model_Observer
{
 /**
  * @var array
  */ 
    protected $blacklist = array('checkout');
 /**
  * Takes a request and redirects it a new url based on some params
  */ 
    public function redirect()
    {
        try
        {
            //Let's get the Request object
            $request = Mage::app()-&gt;getRequest();
            //We only want to redirect in the frontend and exclude the checkout 
            $storeId = Mage::app()-&gt;getStore()-&gt;getId();
            if(!in_array($request-&gt;getModuleName(), $this-&gt;blacklist) &amp;&amp;  $storeId != 0)
            {
                $response = Mage::app()-&gt;getResponse();

                $uri = $request-&gt;getServer("REQUEST_URI"); //requested url
                $temp = strtolower($uri); //lowercase version

                if(strcmp($uri, $temp) != 0) //if the url are different then redirect
                {
                     /**
                      * Dont need to do this but let's get fancy here 
                      */ 
                    $parsedUrl = parse_url(Mage::getBaseUrl());
                    $scheme = $parsedUrl['scheme'];
                    $host = $parsedUrl['host'];
                    $path = $parsedUrl['path'];
                     //build the url
                    $url = $scheme . '://' . $host . $temp;
                    /**
                     * return the response, note the sendHeaders() method
                     * If you don't add it Magento [Zend_Framework] won't redirect you
                     */ 
                    return $response-&gt;setRedirect($url, 301)-&gt;sendHeaders();
                }
            }
        }
        catch(Exception $e)
        {
            Mage::logException($e);
        }
    }
}

&lt;/pre&gt;Let's enable this module, create an xml file under app/etc/modules and name it FooBar_Redirect.xml and add this to it: &lt;br /&gt;
&lt;pre class="brush: xml"&gt;&lt;config&gt;
    &lt;modules&gt;
        &lt;FooBar_Redirect&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codepool&gt;community&lt;/codePool&gt;
        &lt;/FooBar_Redirect&gt;
    &lt;/modules&gt;
&lt;/config&gt;
&lt;/pre&gt;&lt;br /&gt;
Now just clear Magento's cache and simply visit your site. If you type http://mysite_url.com/UpperUrl you should be redirected to http://mysite_url.com/upperurl. &lt;br /&gt;
Now imagine what you can do with this when you have to create a 301 redirect for an entire site, isn't this easier than creating an htacces rule for each url?&lt;br /&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2011/02/magento-301-redirects.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4720634742521623111.post-8788691695776691202</guid><pubDate>Thu, 10 Feb 2011 14:59:00 +0000</pubDate><atom:updated>2011-02-10T09:59:22.767-05:00</atom:updated><title>My first mobile blog post</title><description>&lt;div&gt;&lt;p&gt;This Blogger app is sweet. I cannot believe that they took so long to build it.&lt;/p&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Don't forget to leave your comments.&lt;/div&gt;</description><link>http://www.kingletas.com/2011/02/my-first-mobile-blog-post.html</link><author>noreply@blogger.com (Anonymous)</author><thr:total>0</thr:total></item></channel></rss>