There is a feature started from php 5.5 to get class name with full namespace with magic built in class
constant. For example
<?php
namespace Something\Obscenely\Long\Hard\To\Type;
class MyClass {
}
echo MyClass::class;
// Output: Something\Obscenely\Long\Hard\To\Type\MyClass
?>
Here is links for documentation and RFC http://php.net/oop5.basic#language.oop5.basic.class.class https://wiki.php.net/rfc/class_name_scalars
The question is:
If I use Zend Framework 2, for example, which known as framework with huge php arrays configs, if I use for every class name in this configs resolution method with ::class
against just full names typed like strings ''
- is there a valuable performance impact?
For example:
'controllers' => [
'invokables' => [
'\Controller\Monitor' => 'Import\Controller\MonitorController',
...
vs
'controllers' => [
'invokables' => [
'\Controller\Monitor' => MonitorController::class,
...
UPD:
My own tests
I write simple fast test to benchmark
class MyClass
{
}
class MyClass1
{
}
class MyClass2
{
}
class MyClass3
{
}
/**
* run many iteration loop for test percentage
*/
function testString()
{
$results = [];
for ($i = 0; $i < 150000; $i++) {
$results[] = [
'controllers' => [
'invokables' => [
'\Controller\Monitor' => 'Import\Controller\MonitorController',
'\Controller\Monitor2' => 'Import\Controller\MonitorController2',
'\Controller\Monitor3' => 'Import\Controller\MonitorController3',
'\Controller\Monitor4' => 'Import\Controller\MonitorController4',
]
]
];
}
return $results;
}
function testClass()
{
$results = [];
for ($i = 0; $i < 150000; $i++) {
$results[] = [
'controllers' => [
'invokables' => [
'\Controller\Monitor' => MyClass::class,
'\Controller\Monitor2' => MyClass1::class,
'\Controller\Monitor3' => MyClass2::class,
'\Controller\Monitor4' => MyClass3::class,
]
]
];
}
return $results;
}
$token = Benchmark::start('testString');
testString();
Benchmark::end($token);
$token = Benchmark::start('testClass');
testClass();
Benchmark::end($token);
exit();
And results is similar to
testString
215335.203125 Kbytes
Time: 0.2604 Seconds
testClass
215337.1640625 Kbytes
Time: 0.2508 Seconds
We can see that ::class
is faster. Run with latest php5.6.
Can it be true ?
P.S. It's not a duplicate of How to measure PHP code because:
I don't know how to measure performance in this question context, because for this case running benchmark not enough and difficult.
It's not simple to change thousands lines of code in real project config files.
When you have ::class
in your code, what actually happens is that PHP takes the name of the class you've specified and generates the fully-qualified namespaced classname as a string. So yes, this does indeed mean that you're getting the computer to do more work than if you'd just supplied a string.
However, it does this at compile time. This means that it will only ever do it once, and it happens outside of the bounds of your program runtime. Therefore your Benchmark
performance timer won't take it into account -- in fact when your code runs, it just sees a string, which means that what you're actually benchmarking is the program doing virtually exactly the same thing in both scenarios. Any difference in timing between the two is an artifact and can be ignored.
The other important point about it being done at compile time is that if you have OpCache enabled then it will only ever have to convert the string once, the first time you run it, which means that there's even less of a difference between the two.
The ::class
syntax wasn't added to the language for performance reasons; it was added because it helps with code quality, readability and maintainability. And frankly, those factors are almost always far more important than micro-optimised performance.
Since it's done at compile time, you can't get an accurate benchmark for it from inside of the PHP program.
If you really want to benchmark it, your best option would be to write a shell script with a timer and call the program from there. You'll need to have a separate PHP program for each variation. But even then, any benchmark results you get will be somewhat artificial and unlikely to be useful in any meaningful way. You'll get different results depending on whether you run multiple loops in a single instance of the program or have the loop in the shell script. You'll also get different results if you have OpCache enabled.
But ultimately, you really shouldn't even be thinking about whether to benchmark this -- it's a syntax nicety; it doesn't affect performance. Or if it does, the effect is so tiny that it's not worth thinking about.
The secret of good performance tuning is to find the biggest bottlenecks in your code, and deal with them first. Not the smallest.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With