有一个功能从php 5.5开始,获取具有完整命名空间的类名,其中魔法内置class
常量。例如
<?php
namespace Something\Obscenely\Long\Hard\To\Type;
class MyClass {
}
echo MyClass::class;
// Output: Something\Obscenely\Long\Hard\To\Type\MyClass
?>
以下是文档和RFC的链接 http://php.net/oop5.basic#language.oop5.basic.class.class https://wiki.php.net/rfc/class_name_scalars
问题是:
如果我使用Zend Framework 2,例如,已知为具有巨大php数组配置的框架,如果我在此configs解析方法中使用::class
的每个类名,而不是仅使用类型为字符串{{ 1}} - 是否会产生有价值的性能影响?
例如:
''
VS
'controllers' => [
'invokables' => [
'\Controller\Monitor' => 'Import\Controller\MonitorController',
...
UPD:
我自己的测试
我将简单的快速测试写入基准测试
'controllers' => [
'invokables' => [
'\Controller\Monitor' => MonitorController::class,
...
结果与
类似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();
我们可以看到testString
215335.203125 Kbytes
Time: 0.2604 Seconds
testClass
215337.1640625 Kbytes
Time: 0.2508 Seconds
更快。运行最新的php5.6。
真的可以吗?
P.S。它与如何衡量PHP代码并不重复,因为:
我不知道如何衡量这个问题背景下的表现, 因为对于这种情况,运行基准测试不够和困难。
在实际项目中更改数千行代码并不简单 配置文件。
答案 0 :(得分:20)
如果代码中有::class
,那么实际发生的是PHP获取您指定的类的名称并生成完全限定的命名空间类名作为字符串。所以是的,这确实意味着你让计算机做的工作比你刚提供字符串要多。
但是,它在编译时执行 。这意味着它只会执行一次,并且它发生在程序运行时的范围之外。因此,您的Benchmark
性能计时器不会将其考虑在内 - 实际上当您的代码运行时,它只会看到一个字符串,这意味着您实际进行基准测试的是程序执行几乎完全相同的事情。两种情况。两者之间的时间差异是一个人工制品,可以忽略不计。
关于它在编译时完成的另一个重点是,如果你启用了OpCache,那么它只需要在第一次运行它时将字符串转换一次,这意味着它们之间的区别更小两个。
出于性能原因,未将::class
语法添加到语言中;之所以添加,是因为它有助于提高代码质量,可读性和可维护性。坦率地说,这些因素几乎总是比微观优化的表现更重要。
由于它是在编译时完成的,因此无法从PHP程序内部获得准确的基准。
如果你真的想要对它进行基准测试,你最好的选择就是用一个定时器编写一个shell脚本并从那里调用程序。您需要为每个变体都有一个单独的PHP程序。但即便如此,您获得的任何基准测试结果都会有些人为,并且不可能以任何有意义的方式发挥作用。根据您是在程序的单个实例中运行多个循环还是在shell脚本中使用循环,您将获得不同的结果。如果启用了OpCache,您也会得到不同的结果。
但最终,你真的不应该考虑是否对此进行基准测试 - 这是一种语法准确;它不会影响性能。或者如果确实如此,效果非常小,不值得考虑。
良好性能调优的秘诀在于找到代码中最大的瓶颈,并首先处理它们。不是最小的。