Подтвердить что ты не робот

Производительность расширения переменных по сравнению с sprintf в PHP

Что касается производительности, есть ли разница между выполнением:

$message = "The request $request has $n errors";

и

$message = sprintf('The request %s has %d errors', $request, $n);

в PHP?

Я бы сказал, что вызов функции включает в себя больше вещей, но я не знаю, что PHP делает за кулисами, чтобы расширять имена переменных.

Спасибо!

4b9b3361

Ответ 1

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

$message = sprintf('The request %s has %d errors', $request, $n);

Тем не менее, я считаю, что секунды медленнее (поскольку @Pekka указал, что разница действительно не имеет значения) из-за накладных расходов на вызов функции, разбор строки, преобразование значений и т.д. Но, пожалуйста, обратите внимание, что 2 строки код не эквивалентны, так как во втором случае $n преобразуется в целое число. если $n - "нет ошибки", тогда выводится первая строка:

The request $request has no error errors

Пока будет выведен второй:

The request $request has 0 errors

Ответ 2

Это не имеет значения.

Любое увеличение производительности будет настолько незначительным, что вы увидите его (как улучшение в hundreths секунд) только с 10000 или 100000 итераций - если даже тогда.

Для конкретных номеров см. этот тест. Вы можете видеть, что он должен генерировать 1 МБ + данных, используя 100 000 вызовов функций для достижения измеримой разницы в сотнях миллисекунд. Вряд ли реальная ситуация. Даже самый медленный метод ( "sprintf() с позиционными параметрами" ) занимает всего 0,00456 миллисекунд против 0,00282 миллисекунды с самым быстрым. Для любой операции, требующей 100 000 строковых выходных вызовов, у вас будут другие факторы (например, сетевой трафик), который будет составлять скорость меньше, чем 100 мс, которую вы можете сохранить, оптимизируя это.

Используйте то, что делает ваш код наиболее читаемым и поддерживаемым для вас и других. Для меня лично метод sprintf() является опрятной идеей - я должен думать о том, чтобы начать использовать это сам.

Ответ 3

Анализ производительности "переменное расширение против sprintf" был сделан здесь.

Как говорит @pekka, "делает ваш код наиболее читаемым и поддерживаемым для вас и других". Когда прирост производительности "низкий" (~ менее двух раз), игнорируйте его.

Подведение итогов теста: PHP оптимизирован для разрешений с двойным кавычками и Heredoc. Процентное отношение к среднему времени, к вычислению очень длинной строки, использующей только,

  • разрешение с двойным кавычком: 75%
  • heredoc resolution: 82%
  • конкатенация одной кавычки: 93%
  • sprintf formating: 117%
  • Формирование sprintf с индексированными параметрами: 133%

Обратите внимание, что только sprintf выполняет некоторую задачу форматирования (см. контрольный показатель "% s% s% d% s% f% s" ), и, как показывает @Darhazer, он делает некоторую разницу на выходе. Лучшим тестом является два теста, один из которых сравнивает время конкатенации (формат '% s'), другие - процесс форматирования -— например, "% 3d% 2.2f" и функциональные эквиваленты перед расширением переменных в двойные кавычки... И еще одна контрольная комбинация с использованием коротких строк шаблона.

PROS и CONS

Основным преимуществом sprintf является, как показывают в тестах, очень недорогой форматер (!). Для типовых шаблонов я предлагаю использовать функцию vsprintf.

Основными преимуществами удвоенного котирования (и heredoc) являются некоторые характеристики; и некоторая читаемость и ремонтопригодность номинальных заполнителей, которая растет с количеством параметров (после 1) при сравнении с позиционными метками sprintf.

Использование индексированных заполнителей находится на полпути ремонтопригодности с помощью sprintf.

ПРИМЕЧАНИЕ. Не используйте конкатенацию одиночной кавычки, только если это действительно необходимо. Помните, что PHP включает безопасный синтаксис, например "Hello {$user}_my_brother!", и ссылки типа "Hello {$this->name}!".

Ответ 4

При вводе нескольких строковых переменных в строку, первая будет быстрее.

$message = "The request $request has $n errors";

И Для одной инъекции точка (.) конкатенация будет быстрее.

$message = 'The request '.$request.' has 0 errors';

Сделайте итерацию с циклом миллиарда и найдите разницу.

Например,

<?php

    $request = "XYZ";
    $n = "0";
    $mtime = microtime(true);
    for ($i = 0; $i < 1000000; $i++) {
            $message = "The request {$request} has {$n} errors";
    }
    $ctime = microtime(true);
    echo ($ctime-$mtime);

?>

Ответ 5

В конечном счете первое является самым быстрым при рассмотрении контекста одного присваивания переменной, которое можно увидеть, просмотрев различные контрольные точки. Возможно, однако, использование вкуса sprintf основных функций PHP может позволить более расширяемый код и лучше оптимизироваться для механизмов кэширования уровня байт-кода, таких как opcache или apc. Другими словами, приложение определенного размера может использовать меньше кода при использовании метода sprintf. Чем меньше кода вы должны кэшировать в ОЗУ, тем больше у вас RAM для других вещей или более скриптов. Однако это имеет значение только в том случае, если ваши скрипты не будут правильно вписываться в ОЗУ с использованием оценки.