Skip to content

Instantly share code, notes, and snippets.

@Majkl578
Forked from juzna/intro.md
Created August 21, 2012 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Majkl578/3413675 to your computer and use it in GitHub Desktop.
Save Majkl578/3413675 to your computer and use it in GitHub Desktop.
Nette\Object performance tests

Nette\Object performance tests

I guess you already saw a short note Latency Numbers Every Programmer Should Know. I wanted to check how well Nette performs with its magic properties on Nette\Object.

You can see the testing code below together with raw output on my machine.

It show how much time in seconds it took to execute one million iterations of a particular action, thus it is also time in microseconds of one such call. You should compare it to null test, which execute empty iterations.

Results

Compared to a native getter of public property:

  • method call is cca 4x slower
  • magic getter is cca 15x slower
  • magic getter in form isSomething() is cca 25x slower

Summary

In a real app this does not cause any issue. I tested it on an our eshop where it added only cca 1ms to a page load, which was almost nothing to a total page load time.

<?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;
PHP: 5.4.6
init (mem peak 1310720B)
null: 0.17230796813965 (mem peak 1310720B)
direct: 0.26067900657654 (mem peak 1310720B)
method: 0.49422287940979 (mem peak 1310720B)
magic: 7.4446849822998 (mem peak 1310720B)
magic2: 8.072625875473 (mem peak 1310720B)
plain magic: 1.6670439243317 (mem peak 1310720B)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment