Unserialize vs Include, with APC or php://memory

Posted by John Kleijn • Sunday, December 7. 2008 • Category: PHP

As a follow up on my previous post, I decided it would be interesting to see what effect using the php://memory wrapper or APC would have on the results.


Ran $php bench.php 10000

Without APC

array(3) {

["benchmarkUnserialize"]=>

float(0.271171092987)

["benchmarkUnserializeFromPhpMem"]=>

float(0.105821371078)

["benchmarkInclude"]=>

float(0.421773910522)

}

With APC

array(4) {

["benchmarkUnserialize"]=>

float(0.287040710449)

["benchmarkUnserializeFromPhpMem"]=>

float(0.104715824127)

["benchmarkUnserializeFromApc"]=>

float(0.106453418732)

["benchmarkInclude"]=>

float(0.121370077133)

}

Both the include method and serializing benefit from APC, but serialization stays ahead by an impressive ~20%.

Code on the next page.

Test script:


<?php
class Stopwatch
{
        private $_start;
       
        private $_stop;
       
        private $_elapsed = 0;
       
        public function start()
        {
                $this->_start = microtime(true);       
        }
       
        public function stop()
        {
                $this->_stop = microtime(true);
               
                $this->_elapsed += $this->_stop - $this->_start;
        }
       
        public function getElapsed()
        {
                return $this->_elapsed;
        }
}
class QuickNDirtyBench
{
        const SKIPPED = 'skipped';
       
        private $_serializationFile;
       
        private $_data;
       
        private $_memoryHandle;
       
        public function __construct($serializationFile)
        {
                $this->_serializationFile = $serializationFile;
        }
       
        public function run($i)
        {
                $this->store();
               
                $refl = new ReflectionObject($this);
               
                $results = array();
               
                foreach($refl->getMethods() as $method)
                {
                        if(strpos($method->getName(), 'benchmark') === 0)
                        {
                                $result = $this->bench($method->getName(), $i);
                               
                                if($result === self::SKIPPED)
                                {
                                        continue;
                                }
                               
                                $results[$method->getName()] = $result;
                        }
                }
               
                return $results;
        }
       
        public function bench($method, $i)
        {
                $stopwatch = new Stopwatch();
                       
                for (; $i > 0 ; --$i)
                {
                        $stopwatch->start();
                       
                        $data = $this->{$method}();    
                       
                        $stopwatch->stop();
                       
                        if($data === self::SKIPPED)
                        {
                                break;                 
                        }
                       
                        $this->_data[serialize($data)] = $method;
                }
               
                return $data === self::SKIPPED ? self::SKIPPED : $stopwatch->getElapsed();
        }
       
        public function store()
        {
                $serializedData = serialize($this->benchmarkInclude());
               
                if(extension_loaded('apc'))
                {
                        apc_clear_cache('system');
                        apc_clear_cache('user');
                        apc_store('foo', $serializedData, 60);         
                }
               
                file_put_contents($this->_serializationFile, $serializedData);
               
                file_put_contents("php://memory", $serializedData);
               
                $this->_memoryHandle = fopen("php://memory", 'r+');

                fputs($this->_memoryHandle, $serializedData);
        }
       
        public function benchmarkUnserialize()
        {
                return unserialize(file_get_contents($this->_serializationFile));
        }
       
        public function benchmarkUnserializeFromPhpMem()
        {
                rewind($this->_memoryHandle);
                       
                return unserialize(stream_get_contents($this->_memoryHandle));
        }
       
        public function benchmarkUnserializeFromApc()
        {
                if(!extension_loaded('apc'))
                {
                        return self::SKIPPED;
                }
               
                return unserialize(apc_fetch('foo'));
        }
       
        public function benchmarkInclude()
        {
                return include 'data.php';
        }
       
        public function sanityCheck()
        {      
                $c = count($this->_data);
               
                if($c !== 1)
                {
                        throw new Exception("Sanity check failed on {$this->_data['b:0;']}");
                }
        }
}

$bencher = new QuickNDirtyBench('serialized.txt');

$result = $bencher->run($argv[1]);

var_dump($result);

$bencher->sanityCheck();
 

Test data:


<?php
return array(
        'foo' => 'bar',
        'meh' => array(
                'o' => 'my',
                'god' => 'this',
                'is' => 'very'
        ),
        'tedious',
        'can' => 'you',
        'imagine' => array(
                'you' => array(
                        'would' => array(
                                'have' => 'to',
                                'do',
                                'this' => 'all day long?'
                        )
                )
        )      
);
 

0 Trackbacks

  1. No Trackbacks

0 Comments

Display comments as (Linear | Threaded)
  1. No comments

Add Comment

You can use [geshi lang=lang_name [,ln={y|n}]][/geshi] tags to embed source code snippets.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA


Antiquities and such