views:

149

answers:

2

The title of this question isn't so clear, but the code and question is straightforward.

Let's say I want to show my users an ad once per day. To accomplish this, every time they visit a page on my site, I check to see if a certain memcache key has any data stored on it. If so, don't show an ad. If not, store the value '1' in that key with an expiration of 86400.

I can do this 2 ways:

//version a
$key='OPD_'.date('Ymd').'_'.$type.'_'.$user;
if($memcache->get($key)===false){
 $memcache->set($key,'1',false,$expire);
 //show ad
}

//version b
$key='OPD_'.date('Ymd').'_'.$type.'_'.$user;
if($memcache->add($key,'1',false,$expire)){
 //show ad
}

Now, it might seem obvious that b is better, it always makes 1 memcache call. However, what is the overhead of "add" vs. "get"? These aren't the real comparisons... and I just made up these numbers, but let's say 1 add ~= 1 set ~= 5 get in terms of effort, and the average user views 5 pages a day:

a: (5 get * 1 effort) + (1 set * 5 effort) = 10 units of effort

b: (5 add * 5 effort) = 25 units of effort

Would it make sense to always do the add call? Is this an unnecessary micro-optimization?

+1  A: 

Here's some quick and dirty code I whipped up to test this, if anyone is interested:

<?php
require('include.php');
$memcache = new Memcache();

foreach(Config::$CONFIG['memcache_server'] as $memcache_server){
    $memcache->addServer($memcache_server,11211,false);
}

$iterations = 300;
$max_pages_per_visit = 25;

$time_now = microtime(true);
for($pages_per_visit = 1; $pages_per_visit<=$max_pages_per_visit; $pages_per_visit++){
    foreach(array('gs','a') as $method){
        $start = microtime(true);
        for($x = 0; $x < $iterations; $x++){
            $key = 'testmc'.$time_now.'_'.$pages_per_visit.'_'.$method.'_'.$x;
            switch($method){
                case 'gs':
                    for($y = 0 ; $y < $pages_per_visit; $y++){
                        if($memcache->get($key)===false){
                            $memcache->set($key,'1',null,5);
                        }
                    }
                    break;
                case 'a':
                    for($y = 0 ; $y < $pages_per_visit; $y++){
                        $memcache->add($key,'1',null,5);
                    }
                    break;
            }
        }
        $end = microtime(true);
        $results[$pages_per_visit][$method] = $end - $start;
    }
}

//print results
print('<pre>');
foreach($results as $pages_per_visit => $data){
    $speed_diff = $data['gs'] - $data['a'];
    $speed_percentage = round($speed_diff / $data['gs'] * 100,2);
    echo($pages_per_visit.' pages : add is faster by :'.$speed_diff.' ('.$speed_percentage.')%'.PHP_EOL);
}
Mike Sherov
And the results?
Software Monkey
For my cluster of machines, add beats get/set until About 22 pages per visit... After that, get/set wins.
Mike Sherov
A: 

If you know the key exists, it would probably be faster to do an increment operation and look at the results. This is similar to the rate limiting and throttling problems that people encounter; you could probably craft a good Google search knowing that.

Nick Gerakines