PHP:类名常量与字符串性能

标签 php performance zend-framework2

从 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 数组配置的框架,如果我在这个配置解析方法中使用每个类名 ::class 而不是全名像字符串一样输入 '' - 对性能有重要影响吗?

例如:

'controllers' => [
        'invokables' => [
            '\Controller\Monitor'  => 'Import\Controller\MonitorController',
...

对比

'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

我们可以看到 ::class 更快。使用最新的 php5.6 运行。

这是真的吗?

附言它不是如何衡量 PHP 代码的副本,因为:

  1. 在搜索引擎中没有我要询问的信息。
  2. 我不知道如何衡量这个问题上下文中的性能, 因为对于这种情况,运行基准测试还不够而且困难。

  3. 在真实项目中改几千行代码并不简单 配置文件。

  4. 我想要更详细的答案 - 不仅是数字,还有 还有为什么?

最佳答案

当您的代码中包含 ::class 时,实际发生的是 PHP 获取您指定的类的名称并生成完全限定的命名空间类名作为字符串。所以,是的,这确实意味着你让计算机做的工作比你只提供一个字符串要多。

但是,它在编译时执行此操作。这意味着它只会执行一次,并且它发生在程序运行时的范围之外。因此,您的 Benchmark 性能计时器不会将其考虑在内——实际上,当您的代码运行时,它只会看到一个字符串,这意味着您实际进行基准测试的是程序几乎完全在两种情况下都是一样的。两者之间的任何时间差异都是人为因素,可以忽略不计。

关于它在编译时完成的另一个重要点是,如果你启用了 OpCache,那么它只需要转换一次字符串,在你第一次运行它时,这意味着两者之间的差异更小两个。

出于性能原因,::class 语法没有添加到语言中;添加它是因为它有助于提高代码质量、可读性和可维护性。坦率地说,这些因素几乎总是比微优化性能重要得多。

基准测试的进一步说明

由于它是在编译时完成的,因此您无法从 PHP 程序内部获得准确的基准测试。

如果您真的想对其进行基准测试,最好的选择是编写一个带有计时器的 shell 脚本并从那里调用程序。每个变体都需要一个单独的 PHP 程序。但即便如此,您获得的任何基准测试结果都会有些人为因素,并且不太可能以任何有意义的方式发挥作用。根据您是在程序的单个实例中运行多个循环还是在 shell 脚本中有循环,您会得到不同的结果。如果您启用了 OpCache,您也会得到不同的结果。

但归根结底,您真的不应该考虑是否要对此进行基准测试——这是一种语法上的好处;它不会影响性能。或者即使有,影响也很小,不值得考虑。

良好性能调优的秘诀是找到代码中最大的瓶颈,并首先解决它们。不是最小的。

关于PHP:类名常量与字符串性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32630331/

相关文章:

php - 使用php将部分文本从mysql更改为变量名

Sql IN 子句会降低性能

mysql - 多个相等性测试的效率与 MySQL 中的连接

php - 更改 Zend Framework 2 默认模板解析器行为

php - 在 Zend Framework 2 中禁用某些选项选择

zend-framework2 - 禁用默认 zfcUser 路由?

javascript - 带有 li & ul 的多级下拉列表,带有 PHP 数组循环,带有 CSS 和 jQuery

php - 试图在一个小时内取60个点的平均值,然后以图表形式输出

php - 如何用PHP只显示数据库列的一个字段

c++ - 获取系统时间和用户时间