PHP: Константа имени класса против производительности строки


Существует функция, запущенная с 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.

Может ли это быть правдой?

P.S. Это не дубликат того, как измерьте PHP-код, потому что:

  1. В поисковых системах нет информации о том, о чем я спрашиваю.
  2. Я не знаю, как измерить производительность в контексте этого вопроса, потому что для этого случая запуск бенчмарка недостаточен и сложен.

  3. Непросто изменить тысячи строк кода в реальных конфигурационных файлах проекта.

  4. Я хочу получить более подробный ответ - не только цифры, но и почему?
Author: Oleg Abrazhaev, 2015-09-17

1 answers

Когда в вашем коде есть ::class, на самом деле происходит то, что PHP принимает имя указанного вами класса и генерирует полное имя класса в пространстве имен в виде строки. Так что да, это действительно означает, что вы заставляете компьютер выполнять больше работы, чем если бы вы просто предоставили строку.

Однако он делает это во время компиляции . Это означает, что он будет делать это только один раз, и это происходит за пределами времени выполнения вашей программы. Поэтому ваш Benchmark таймер производительности не будет принимать это во внимание - на самом деле, когда ваш код запускается, он просто видит строку, что означает, что вы на самом деле проводите сравнительный анализ, так как программа делает практически одно и то же в обоих сценариях. Любая разница во времени между ними является артефактом и может быть проигнорирована.

Другой важный момент, связанный с тем, что это делается во время компиляции, заключается в том, что если у вас включен OpCache, то ему придется конвертировать строку только один раз, при первом запуске, что это означает, что между ними еще меньше разницы.

Синтаксис ::class не был добавлен в язык по соображениям производительности; он был добавлен, потому что он помогает улучшить качество кода, читаемость и удобство обслуживания. И, честно говоря, эти факторы почти всегда гораздо важнее, чем микрооптимизированная производительность.

Дальнейшее разъяснение по бенчаркингу

Поскольку это делается во время компиляции, вы не можете получить точный тест для этого изнутри PHP программа.

Если вы действительно хотите протестировать его, лучшим вариантом было бы написать сценарий оболочки с таймером и вызвать программу оттуда. Вам понадобится отдельная PHP-программа для каждого варианта. Но даже в этом случае любые результаты тестов, которые вы получите, будут несколько искусственными и вряд ли будут полезны каким-либо значимым образом. Вы получите разные результаты в зависимости от того, выполняете ли вы несколько циклов в одном экземпляре программы или имеете цикл в сценарии оболочки. Вы также будете получите другие результаты, если у вас включен OpCache.

Но, в конечном счете, вам действительно не следует даже думать о том, стоит ли сравнивать это - это тонкость синтаксиса; это не влияет на производительность. А если и так, то эффект настолько мал, что об этом не стоит и думать.

Секрет хорошей настройки производительности заключается в том, чтобы найти самые большие узкие места в вашем коде и сначала разобраться с ними. Не самый маленький.

 14
Author: Simba, 2015-09-17 14:14:42