0

I knew that I can use variable variables instead of reflection in PHP but I have never gone that way because my OOP background stated that this is not a clean way. Recently I made a test using both methods and the results made me rethink it.

Using variable variables is really less time consuming (almost 50%). My considerations now is how stable is this way. Is this behavior something that is in PHP and is not going to change? Sharing your opinions about that, tell me the disadvantages / advantages each way you think has. Thank you in advance for your responses.

<?php
// A simple test object
class testObj
{
	private $id;
	
	public function getId()
	{
		return $this->id;
	}
	
	public function setId($newId)
	{
		$this->id = $newId;
	}
}

//Variable variables way 
$startTime1 = microtime(true);
$a = "testObj";
$method = "setId";
$test1 = new $a; 
$test1->$method(33);
$endTime1 = microtime(true);
echo "Variable variables way: ".(number_format($endTime1 - $startTime1,10))."<br/>";
var_dump($test1);

echo "<br/><br/>";
// Reflection way 
$startTime2 = microtime(true);
$a = "testObj";
$method = "setId";
$reflectionClass = new ReflectionClass($a);
$test2 = $reflectionClass->newInstance();
$reflectionMethod = $reflectionClass->getMethod($method);
$reflectionMethod->invoke($test2,33);
$endTime2 = microtime(true);
echo "Reflection way: ".(number_format($endTime2 - $startTime2,10))."<br/>";
var_dump($test2);

?>
4
Contributors
10
Replies
11
Views
6 Years
Discussion Span
Last Post by bato3
1

My results are right on par with what you are seeing. Reflection is about twice as slow as using variable variables. I also benchmarked call_user_func and found that to be just about on par with the variable variable calls. I can't say I've seen reflection used as much as I've seen a mixture of variable class and method calls and call_user_func calls. Probably because of the performance hit.

PHP 5.3 added the ability to do variable static method calls $class::$staticMethod() , so I believe this is something that is here to stay in PHP.

Running Benchmark: Compare Variable Variables To Reflection To Call_User_Func
======================================================================
Running Test: test_Variable_Variable
	Cycles: 	 10000
	Mean: 		 0.0000545718 secs.
	Median: 	 0.0000410080 secs.
	Mode: 		 0.0000410080 secs.
	Range: 		 0.0287699699 secs.
	Min: 		 0.0000379086 secs.
	Max: 		 0.0288078785 secs.
======================================================================
Running Test: test_Reflection
	Cycles: 	 10000
	Mean: 		 0.0000928412 secs.
	Median: 	 0.0000720024 secs.
	Mode: 		 0.0000720024 secs.
	Range: 		 0.0295591354 secs.
	Min: 		 0.0000679493 secs.
	Max: 		 0.0296270847 secs.
======================================================================
Running Test: test_Call_User_Func
	Cycles: 	 10000
	Mean: 		 0.0000557658 secs.
	Median: 	 0.0000460148 secs.
	Mode: 		 0.0000460148 secs.
	Range: 		 0.0230920315 secs.
	Min: 		 0.0000429153 secs.
	Max: 		 0.0231349468 secs.
======================================================================
0

Thank you mschroeder for your answer. Variable variables are also reflection by the larger meaning of the word; I avoided them because I have seen them in use producing really mixed code. Now I am going to use them instead of reflection classes, in the core of my applications (-framework) due to performance hit.

Partially irrelevant, but what test software did you used for your benchmark?

0

I would argue that the practice of optimizing essential components of an application does not affect the overall performance of an application. You should be concerned about other areas that do affect performance, such as caching the instances (singleton pattern), lazy loading etc. These do affect performance of a framework.

The plus of using Reflection is that it allows arbitrary number of arguments to the constructor.

eg:

// create instance with arbitrary parameters
$instance = call_user_func_array(
   array(new ReflectionClass('classname'), 'newInstance'), 
   array('param1', 'param2')
);

// call the method passing arbitrary parameters
$return = call_user_func_array(
   array($instance, 'methodname'), 
   array('param1', 'param2')
);

This would be the same as the static:

$instance = new classname('param1', 'param2');
$instance->methodname('param1', 'param2');

n/b: Here 'param1' and 'param2' can be any number of arguments of different types.

This could be useful for dependency injection. You can add instances required by a plugin or specific configurations etc. to the constructor when instantiating arbitrary plugin classes. Basically any class that needs customization on instantiation would benefit.

Edited by digital-ether: n/a

0

I can’t understand the “I would argue that the practice of optimizing essential components of an application does not affect the overall performance of an application” if is something that I am missing, please explain it further digital-ether, in order to extend my views. Of course there are 1000 (and maybe more) things to a framework, to pay attention to … but one of them (and in any application) is reflection.

The performance hit, airsidelimo, is great when you compare these two methods, but in real life project it vanishes, if you don’t for example make the correct adjustments to an image. Of course this is not a reason always trying the best for your app. And if the performance hit is in the core of your applications will live for ever.

I am still against variable variables way (due to the code that is produced) but … maybe for core (lib or framework) has meaning …

Edited by jkon: n/a

0

I can’t understand the “I would argue that the practice of optimizing essential components of an application does not affect the overall performance of an application” if is something that I am missing, please explain it further digital-ether, in order to extend my views. Of course there are 1000 (and maybe more) things to a framework, to pay attention to … but one of them (and in any application) is reflection.

The performance hit, airsidelimo, is great when you compare these two methods, but in real life project it vanishes, if you don’t for example make the correct adjustments to an image. Of course this is not a reason always trying the best for your app. And if the performance hit is in the core of your applications will live for ever.

I am still against variable variables way (due to the code that is produced) but … maybe for core (lib or framework) has meaning …

I think you answered it - "The performance hit, airsidelimo, is great when you compare these two methods, but in real life project it vanishes."

To put it into perspective:

Loading a PHP file from disk is ~0.002 secs on my laptop. I wouldn't put this into consideration for the design of my application and limit the number of file loads the application does or just write it out in one file.

Or put it another way, concatenating strings is slower then concatenating array keys for long strings. I'm not going to use arrays instead of strings when templating (long HTML strings).

Or another, concatenating with single quotes is about twice as fast as double quotes with string interpolation. I'm not going to drop using single quotes altogether.

Or another. Calling functions is about 10 times faster then calling class methods. I'm not going to drop calling methods because of this, or refrain from using objects. Actually, this is likely why using Reflection is slower then the variables method being discussed here.

Good reads:

Premature optimization: http://c2.com/cgi/wiki?PrematureOptimization
And http://en.wikipedia.org/wiki/Program_optimization
And http://www.bluebytesoftware.com/blog/2010/09/06/ThePrematureOptimizationIsEvilMyth.aspx

Also good reads on optimizing/performance limits:
http://en.wikipedia.org/wiki/Big_O_notation
http://en.wikipedia.org/wiki/Computational_complexity_theory

0

Thank you digital-ether for your reply and the links you provided. I believe that the views in this topic are really helpful for me, I hope for others too…

0

@mschroeder: In your test you use above code?
Probably this way can be faster:

$reflectionMethod = new ReflectionMethod('HelloWorld', 'sayHelloTo');
echo $reflectionMethod->invokeArgs(new HelloWorld(), array('Mike'));
This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.