Я провел несколько аналогичных экспериментов с использованием сгенерированного массива:
$a = [];
for($i = 0; $i < 10000; $i ++)
$a[] = $i;
Чтобы рассчитать их, я просто сохраняю microtime
до выполнения и вычитаю его из microtime
после выполнения.Я выполнил код 10 раз и взял среднее.
Сначала я попробовал нечто похожее на ваш первый подход:
$output = '';
foreach($a as $k => $v)
$output = $output . "some static text" . $v . "some other text";
Это записало безумное время ~3s
!Затем я попробовал тот же код, используя одинарные кавычки, и получил тот же результат.
Затем я изменил строку конкатенации на:
$output .= 'some static text' . $v . 'some other text';
Это привело к времени ~0.007s
, ~ 429в разы быстрее!
Наконец я изменил код на:
$output = '';
ob_start();
foreach($a as $k => $v)
echo 'some static text' . $v . 'some other text';
$output = ob_get_clean();
И набрал незначительно медленнее, чем .=
подход (все еще ~0.007
).
Отказ от ответственности: все, что следует, является лишь моей интуицией о том, почему времена такие, какие они есть.
Теперь я не эксперт по внутренним компонентам PHP, но я быПредположим, что причина, по которой первый метод намного медленнее, заключается в том, что он должен создать новую строку и скопировать старую (которая постепенно достигает конечного размера ~350,000
символов) 10,000
раз, и копированиекак правило, довольно неэффективная операция.Однако подход .=
просто расширяет исходную строку, избегая операций копирования.Буферный подход аналогичен, вероятно, потому что запись в выходной поток по стоимости аналогична расширению переменной, с ob_start
и ob_get_clean
, добавляющими предельные издержки.