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

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

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

а также

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

в PHP?

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

Благодаря!

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

 $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 

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

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

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

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

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

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

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

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

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

За и против

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

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

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

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

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

 $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); ?> 

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