Производительность расширения переменных против sprintf в PHP - PullRequest
19 голосов
/ 22 августа 2011

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

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

и

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

в PHP?

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

Спасибо!

Ответы [ 5 ]

31 голосов
/ 22 августа 2011

Неважно.

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

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

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

26 голосов
/ 22 августа 2011

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

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

Тем не менее, я считаю, что секунды медленнее (как указал @Pekka, разница на самом деле не имеет значения), из-за накладных расходоввызов функции, синтаксический анализ строки, преобразование значений и т. д. Обратите внимание: две строки кода не эквивалентны, поскольку во втором случае $ n преобразуется в целое число.если $ n равно «no error», первая строка выведет:

The request $request has no error errors

, а вторая выведет:

The request $request has 0 errors
20 голосов
/ 31 августа 2012

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

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

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

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

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

плюсы и минусы

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

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

Использование индексированных заполнителей находится на полпути обслуживания с sprintf.

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

2 голосов
/ 10 февраля 2014

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

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

?>
0 голосов
/ 15 июня 2016

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

...