Monday June 9, 2008
I’ve seen some interesting benchmarks (1, 2) regarding PHP’s performance when it comes to static methods. The results were somewhat contradictory.
I usually don’t program strictly by following “optimization tricks” that will only save a nanosecond somewhere, yet I try to keep on top of what is slower than other things.
Here are my results (ORDER BY time DESC):
| Which method | Time |
|---|---|
| Inline calculation | 0.0805 s |
| Normal function call | 0.3438 s |
| Normal method called through object | 0.4118 s |
| Static method called statically | 0.4280 s |
| Unspecified method called through object | 0.4294 s |
| Unspecified method called statically | 0.6960 s |
The test was conducted on PHP 5.2.1. This is what most benchmarks report, however most do not include doing the calculation inline. Doing the calculation directly in the loop is of course the fastest. This is probably only useful in situations where you’ve squeezed every last bit of juice out of the loop already, yet the speed improvement is very large.
Also that a method not declared static, yet being called statically, will be almost 60 percent slower than if it were declared static. This clearly conflicts with what Reinhold Weber wrote:
If a method can be static, declare it static. Speed improvement is by a factor of 4.
There is a speed improvement, yet nowhere near a factor of four. Lesson learned: do your own benchmarks. And by all means, if a method can be static, make it static. The speed improvement just isn’t by a factor of four.
This code uses my Timer.php class, which you can get here. I wrote Timer.php a while ago, before I found out about Xdebug, but it works really well.
<?php require_once('Timer.php'); define('ITERATIONS', 100000); $t = new Timer(false, true); if ($_GET['clear']) $t->clearStatistics();class Test { public static function StaticTest() { return 2 + 2; }public function Test() { return 2 + 2; }function AmbigiousTest() { return 2 + 2; } }function Test() { return 2 + 2; }$test = new Test();$t->startClock(); for ($i = 0; $i < ITERATIONS; $i++) { Test::StaticTest(); } $t->mark('Static method called statically');for ($i = 0; $i < ITERATIONS; $i++) { $test->Test(); } $t->mark('Normal method called through object');for ($i = 0; $i < ITERATIONS; $i++) { Test::AmbigiousTest(); } $t->mark('Unspecified method called statically');for ($i = 0; $i < ITERATIONS; $i++) { $test->AmbigiousTest(); } $t->mark('Unspecified method called through object');for ($i = 0; $i < ITERATIONS; $i++) { Test(); } $t->mark('Function call'); for ($i = 0; $i < ITERATIONS; $i++) { 2 + 2; } $t->mark('Inline calculation'); $t->stopClock(true); ?>
Comments