Unserialize vs Include, with APC or php://memory
Posted by John Kleijn • Sunday, December 7. 2008 • Category: PHPAs 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:



ShareThis