|
<?php |
|
/** |
|
* Comparing speed of: |
|
* - native property access |
|
* - getter method |
|
* - magic property access on nette object ($x->name --> $x->getName()) |
|
* - magic property access with isBar() method |
|
*/ |
|
|
|
require_once __DIR__ . '/vendor/nette/Nette/loader.php'; // clone Nette (git clone git://github.com/nette/nette.git) into vendor |
|
|
|
|
|
echo "PHP:\t", PHP_VERSION, PHP_EOL; |
|
echo "init \t(mem peak ", memory_get_peak_usage(TRUE), 'B)', PHP_EOL; |
|
echo PHP_EOL; |
|
|
|
const ITERATIONS = 1e6; |
|
|
|
|
|
/** |
|
* Class under test |
|
*/ |
|
class Foo extends \Nette\Object |
|
{ |
|
public $name1; |
|
private $name2; |
|
|
|
public function __construct($s) |
|
{ |
|
$this->name1 = $s; |
|
$this->name2 = $s; |
|
} |
|
|
|
public function getName1() { return $this->name1; } |
|
public function getName2() { return $this->name2; } |
|
public function isName3() { return $this->name2; } |
|
|
|
} |
|
|
|
class Bar |
|
{ |
|
private $name; |
|
|
|
public function __construct($s) |
|
{ |
|
$this->name = $s; |
|
} |
|
|
|
public function getName() |
|
{ |
|
return $this->name; |
|
} |
|
|
|
public function __get($name) |
|
{ |
|
return $this->{'get' . $name}(); |
|
} |
|
} |
|
|
|
|
|
/***************** helpers *****************j*d*/ |
|
|
|
function slowdown($t1, $t0) |
|
{ |
|
return round(($t1 - $t0) / ITERATIONS * 1e6, 3) . 'us'; |
|
} |
|
|
|
/***************** eof: helpers *****************j*d*/ |
|
|
|
$refString = 'foo'; // use same value everywhere, profit from interned strings in php >=5.4 |
|
|
|
// make sure that it all works as expected |
|
$foo = new Foo($refString); |
|
$bar = new Bar($refString); |
|
//assert(false); |
|
assert($foo->getName1() === $refString); |
|
assert($foo->getName2() === $refString); |
|
assert($foo->name1 === $refString); |
|
assert($foo->name2 === $refString); |
|
assert($foo->name3 === $refString); |
|
assert($bar->getName() === $refString); |
|
assert($bar->name === $refString); |
|
|
|
/***************** test 0 - empty assignment in cycle *****************j*d*/ |
|
$x = NULL; |
|
$t = microtime(true); |
|
for($i = 0; $i < ITERATIONS; $i++) { |
|
$x = $refString; |
|
} |
|
echo "null:\t", $result0 = microtime(true) - $t, "\t\t(mem peak ", memory_get_peak_usage(TRUE), 'B)', PHP_EOL; |
|
|
|
|
|
|
|
/***************** test 1 - direct property access *****************j*d*/ |
|
$x = NULL; |
|
$t = microtime(true); |
|
for($i = 0; $i < ITERATIONS; $i++) { |
|
$x = $foo->name1; |
|
} |
|
echo "direct:\t", $result1 = microtime(true) - $t, "\t\t(mem peak ", memory_get_peak_usage(TRUE), 'B)', PHP_EOL; |
|
|
|
|
|
|
|
/***************** test 2 - getter method call *****************j*d*/ |
|
$x = NULL; |
|
$t = microtime(true); |
|
for($i = 0; $i < ITERATIONS; $i++) { |
|
$x = $foo->getName2(); |
|
} |
|
echo "method:\t", $result2 = microtime(true) - $t, "\t\t(mem peak ", memory_get_peak_usage(TRUE), 'B)', PHP_EOL; |
|
|
|
|
|
|
|
/***************** test 3 - Nette\Object magic property *****************j*d*/ |
|
$x = NULL; |
|
$t = microtime(true); |
|
for($i = 0; $i < ITERATIONS; $i++) { |
|
$x = $foo->name2; |
|
} |
|
echo "magic:\t", $result3 = microtime(true) - $t, "\t\t(mem peak ", memory_get_peak_usage(TRUE), 'B)', PHP_EOL; |
|
|
|
|
|
|
|
/***************** test 4 - Nette\Object magic property (is) *****************j*d*/ |
|
$x = NULL; |
|
$t = microtime(true); |
|
for($i = 0; $i < ITERATIONS; $i++) { |
|
$x = $foo->name3; |
|
} |
|
echo "magic2:\t", $result4 = microtime(true) - $t, "\t\t(mem peak ", memory_get_peak_usage(TRUE), 'B)', PHP_EOL; |
|
|
|
|
|
|
|
/***************** test 5 - PHP plain magic property (getter) *****************j*d*/ |
|
$x = NULL; |
|
$t = microtime(true); |
|
for($i = 0; $i < ITERATIONS; $i++) { |
|
$x = $bar->name; |
|
} |
|
echo "plain magic:\t", $result4 = microtime(true) - $t, "\t\t(mem peak ", memory_get_peak_usage(TRUE), 'B)', PHP_EOL; |