Magic functions are definitely slower than anything else in PHP, and should be used carefully. This would actually be a good blog subject (auto-creating attributes with magic functions to speed things up... anyway). As El Yobo stated, I modified your PHP script so the tests are more accurate :
<?php
class A {
public function __get($a) {
return 5;
}
}
class B {
public $a = 5;
}
class C {
private $a = 5;
public function __get($a) {
return $this->a;
}
}
$classes = array('A','B','C');
header('Content-type: text/plain; charset=utf-8');
foreach ($classes as $className) {
$a = new $className;
$start = microtime(true);
for ($i=0; $i < 1000000; $i++) {
$b = $a->a;
}
$end = microtime(true);
echo 'Class ' . get_class($a) . ' = ' . (($end - $start) * 1000) ." msec\n";
}
Resulting in
Class A = 378.85212898254 msec
Class B = 109.26413536072 msec
Class C = 423.51794242859 msec
So, there you have it. You can clearly see that magic functions, when used, take about 4 times more to execute than public methods.
** EDIT **
Now, if you dynamically create new class attribute, the magic method will be called only the first time, then any subsequent call will access the dynamically created public attribute (public for backward compatibility). Change class C to :
class C {
public function __get($a) {
$this->a = 5;
return 5;
}
}
Will output
Class A = 392.09413528442 msec
Class B = 110.16988754272 msec
Class C = 96.771955490112 msec
So this why you say : "Hey! It's faster!" However, look if we reduce the iterations from 1000000
to 10
(for example):
Class A = 0.033140182495117 msec
Class B = 0.0078678131103516 msec
Class C = 0.01215934753418 msec
Class C is now slower than B because it's initial call to the magic method. My best guess would be that PHP handles dynamically created attributes different than declared ones. But after further research, these results may vary depending on OS, CPU arch, memory, PHP version, etc. Therefore these results cannot be taken for granted, and, generally speaking, magic methods will always take longer to execute than using declared public attributes or calling declared public methods.
** EDIT 2 **
Here's the class D test, skipping the magic method whatsoever with dynamic attribute creation :
class D {
public function __construct() {
$this->a = 5;
}
}
Yields these results for 1000 iterations :
Class A = 1.3999938964844 msec
Class B = 0.42200088500977 msec
Class C = 0.3960132598877 msec
Class D = 0.37002563476562 msec <-- faster
Let's increase our iterations about to 1'000'000 :
Class A = 380.80310821533 msec
Class B = 109.7559928894 msec
Class C = 91.224908828735 msec <-- faster ???
Class D = 96.340894699097 msec
If magic methods have a great overhead cost, the real question now is : Why, when accessing a same attribute repeatedly many times, is
public function __get($a) {
$this->a = 5;
return 5;
}
faster than
public function __construct() {
$this->a = 5;
}
when creating and accessing dynamic attributes?