Ever since Larry Garfield wrote about PHP magic calls and their slow performance I’ve been hesitant to use them. In the time since his post was written in 2007, magic methods have seen improvements and I’ve started taking a look at them again. The first one I’ve started to explore using in the __toString()
method on objects. It turns out, as of PHP 5.3 using the __toString()
magic method can be faster than using regular method calls.
Understanding `__toString()`
When an object is treated as a string the `__toString()` method is called. It gives a class the ability to decide how it will react. For example:/**
* A class named foo with a magic __toString method.
*/
class Foo {
public function __toString() {
return 'foo';
}
}
// $foo is an instance of class Foo.
$foo = new Foo();
// $foo is a class being treated like a string. When it is treated like a
// string the __toString method is called.
// Outputs: foo
print $foo;
Testing `__toString()` vs a `render()` method
In versions of PHP prior to PHP 5.3 there have been tests showing magic methods can be slow. I was warned not to use them for anything that requires performance, like working on a framework or CMS where there will be a lot of users. Recently I had heard magic method performance had improved so I decided to test some of them out and see what happens.The setup
The code I used to perform the tests is:class Foo {
public function render() {
return '';
}
public function __toString() {
return '';
}
}
$foo = new Foo();
$iterations = 1000000;
$start1 = microtime(TRUE);
for ($i = 0; $i < $iterations; $i++) {
print $foo->render();
}
$end1 = microtime(TRUE);
$start2 = microtime(TRUE);
for ($i = 0; $i < $iterations; $i++) {
print $foo;
}
$end2 = microtime(TRUE);
printf("Render Time: %0.2d\n", ($end1 - $start1) * 1000);
printf("toString Time: %0.2d\n", ($end2 - $start2) * 1000);
This fairly simple code tries to be as minimal as possible to highlight the time to call these methods.
The results
What we care about is the results and how they compare to each other, not so much the amount of time they actually take.Render Time: 273
toString Time: 253
Using __toString()
is faster than calling a method on the object to turn it into a string. Here we have a magic method performing quite nicely.