Static vs Non-static methods in PHP: what is faster?

Posted by Stanislav Furman  on May 5, 2014

Static vs Non-static methods in PHP: what is faster?

Some theory

As you know there are two types of methods in PHP classes: static and non-static. To be called a non-static method needs an instance of its class, and static method can be called without instantiating of the class. 

In the meantime there are two very common questions:

  • When to use non-static methods and when to use static methods?
  • Is there any performance difference between static and non-static methods?

These are very common dilemmas among PHP developers. Most of developers guess that static methods must work faster because there is no object instance with all its properties involved to the call. Sounds logical. Is that actually true?

As I already mentioned above, and as you already know, the main difference between static and non-static metods is that static methods do not need an instance of the class to be called in the code. It means that for static methods there is no need to create object and keep in the memory. So, at least we can save some memory which can also affect the performance? Hmmm... we'll see...

So, it's time to do some very simple experiments for further analysis.

Some experiments

To test the performance of static and nonstatic methods let's create two similar classes. The only difference will be how we call methods in the class. To be more precise let's test same classes with different versions of PHP: 5.2, 5.3, 5.4 and 5.5.

Static class

<?php
set_time_limit(0);
Class Static0 {

	public static $counter = 0;
	
	public static function incrByTwo()
	{
		self::$counter = self::$counter + 2;
	}
}

Class Static1 extends Static0 {

	public static function incrByOne()
	{
		self::$counter = self::$counter + 1;
	}
	
	public static function incrByTwo()
	{
		parent::incrByTwo();
	}
}

$time_start = microtime(true);
for($i=0;$i<100000;$i++) {
	Static1::incrByOne();
	Static1::incrByTwo();
}

echo Static0::$counter ;
$time_end = microtime(true);
$time1 = $time_end - $time_start;
?>
Total execution time is <?php echo $time1;?>
Used memory: <?php echo memory_get_usage();?>

NonStatic class

<?php
set_time_limit(0);

Class Static0 {

	public $counter = 0;

	public function incrByTwo()
	{
		$this->counter = $this->counter + 2;
	}
}

Class Static1 extends Static0 {
	
	public function incrByOne()
	{
		$this->counter = $this->counter + 1;
	}
	
	public function incrByTwo()
	{
		parent::incrByTwo();
	}
}

$time_start = microtime(true);
$obj = new Static1();
for($i=0;$i<100000;$i++) {
	$obj->incrByOne();
	$obj->incrByTwo();
}

echo $obj->counter ;

$time_end = microtime(true);
$time1 = $time_end - $time_start;
?>

Total execution time is <?php echo $time1;?>
Used memory: <?php echo memory_get_usage();?>

These are average results that I got after running these tests a few times:

PHP 5.2 : static methods are ~10-15% faster.

PHP 5.3 : non-static methods are ~15% faster

PHP 5.4 : static methods are ~10-15% faster

PHP 5.5 : static methods are ~20% faster

Noticed? Generally, static methods in PHP are faster than non-static ones. The only exception was PHP 5.3 where non-static methods worked faster. Why? Apparently, because of the bug that was in PHP 5.3 when they introduced late static bindings. The bug was fixed in later versions of PHP and as we can see from tests static methods showed faster performance.

In terms of the memory consumption I didn't see any major difference. It was about 1-2% only which is not crucial.

Conclusion

Okay, now we know that static methods are indeed generally faster than non-static methods. And the difference in memory consumption doesn't look significant at all...

So, use static methods everywhere now?

Not really. Short answer to this question would be: you don't need an object and don't need a non-static method if the method doesn't interact with properties or methods in the class and its parents/children.

Yes, static methods look  faster. In the meantime, a lot of developers believe (and they have good reasons) that using static methods and properties break a lot of the power available to Object-Oriented code. They also mention that Unit testing is impossible using static methods.

Classes with static methods are commonly used for general functionalities such as "helpers", factories (i.e. Singleton class initialisation), etc.

Hopefully, this article more or less discloses the subject. Your comments are welcome as usual. ;)


Comments

Egor Spivac says:
May 6, 2014 at 02:12 pm
I think, you have a mistake in your tests. Creation of object in "non static" test should be included in time measuring. So put $obj = new Static1(); under $time_start = microtime(true);
It's just a note. I don't think it will change results :)

Anyway, my test results:

Static
Number of tests 100 * 1000000
Total execution AVG time is 0.093818421363831
Used memory: 238672

Non static
with creation of a new object every time
Number of tests 100 * 1000000
Total execution AVG time is 0.25991368055344
Used memory: 239696

Non static, using one created object.
Number of tests 100 * 1000000
Total execution AVG time is 0.09752377986908
Used memory: 239584

PHP 5.5.9-1ubuntu4 (cli) (built: Apr 9 2014 17:11:57)

We have almost the same results for static/non static if we use one object. If we are creating a new object every time it will be slower.

my tests code:
static:
<?php
set_time_limit(0);

Class simple1 {

public static $counter = 0;

public static function incr()
{
self::$counter++;
}
}

$timeSum = 0;

for ($j = 0; $j < 100; $j++) {
$time_start = microtime(true);
for($i=0; $i<1000000; $i++) {
simple1::incr();
}

$time_end = microtime(true);
$time1 = $time_end - $time_start;
$timeSum += $time1;

echo "Total execution time is {$time1}\n";
echo "Used memory: ".memory_get_usage()."\n";
}


echo "Total execution AVG time is ".($timeSum / 100)."\n";
echo "Used memory: ".memory_get_usage()."\n";
?>

Non static with one global object:
<?php
set_time_limit(0);

Class simple1 {

public $counter = 0;

public function incr()
{
$this->counter++;
}
}

$timeSum = 0;
$obj = new simple1();
for ($j = 0; $j < 100; $j++) {
$time_start = microtime(true);
for($i=0; $i<1000000; $i++) {
$obj->incr();
}

$time_end = microtime(true);
$time1 = $time_end - $time_start;
$timeSum += $time1;

echo "Total execution time is {$time1}\n";
echo "Used memory: ".memory_get_usage()."\n";
}


echo "Total execution AVG time is ".($timeSum / 100)."\n";
echo "Used memory: ".memory_get_usage()."\n";
?>
Flag as SPAM  |  Permalink
Shaharia Azam says:
May 7, 2014 at 07:12 pm
Good article.
Flag as SPAM  |  Permalink
alxy says:
March 2, 2016 at 10:35 pm
like
Flag as SPAM  |  Permalink
Sorwar Hossain says:
July 17, 2017 at 10:03 am
Great article that is
Flag as SPAM  |  Permalink

Leave your comment

Fields with * are required.

* When you submit a comment, you agree with Terms and Conditions of Use.