开发者

memcached: which is faster, doing an add (and checking result), or doing a get (and set when returning false)

开发者 https://www.devze.com 2022-12-27 08:45 出处:网络
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 m

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 memcach开发者_运维技巧e 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?


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);
}


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号