Когда давно, я прочитал, что для повышения производительности кода, необходимо выносить операции условий, до начала цикла. Это правило я распространил на все в том, числе и на длину строки. Т.е. предпочитал вариант:
вместо
Однако, строка в PHP кроме последовательности байт, еще и хранит бинарные данные, характеристики этой строки. В т.ч. информацию о длине строки. Возникает вопрос, какой прирост производительности дает вынос получение длины строки до начала цикла?
Для этого была сформирована строка ~ 5.6 Mb и ее перебрал двумя способами 1000 раз. После чего взял среднее арифметическое значение, для каждого случая. Можно было вычислять медиану, но в данном случае разница получалась незначительной, что позволяет остановится на вычислении СА.
Результат выполнения скрипта:
Разница 0.136201689 сек для строки 5.6 Мб. Из чего можно сделать вывод, в большинстве повседневных задач, получение длины строки можно не выносить до начала цикла. Если же стоит задача работать с очень большими данным, данная оптимизация будет уместна.
$len = strlen($str);
for ($j = 0; $j < $len; $j++)
вместо
for ($j = 0; $j < strlen($str); $j++)
Однако, строка в PHP кроме последовательности байт, еще и хранит бинарные данные, характеристики этой строки. В т.ч. информацию о длине строки. Возникает вопрос, какой прирост производительности дает вынос получение длины строки до начала цикла?
Для этого была сформирована строка ~ 5.6 Mb и ее перебрал двумя способами 1000 раз. После чего взял среднее арифметическое значение, для каждого случая. Можно было вычислять медиану, но в данном случае разница получалась незначительной, что позволяет остановится на вычислении СА.
Результат выполнения скрипта:
- 1.0557837963104 сек — при получение длины строки до начала цикла;
- 1.1919854850769 сек — получение строки в самом условии цикла.
Разница 0.136201689 сек для строки 5.6 Мб. Из чего можно сделать вывод, в большинстве повседневных задач, получение длины строки можно не выносить до начала цикла. Если же стоит задача работать с очень большими данным, данная оптимизация будет уместна.
Листинг тестового скрипта
<?php
// Version 7.2
set_time_limit(5000); // Чтобы по таймауту раньше времени не отвалилась
ini_set('memory_limit', '1024M');
header("Content-Type: text/plain; charset=utf8");
// Для эксперимента создам большую строку
echo 'Strart ';
$str = '';
for ($i = 0; $i < 1000000; $i++){ // 5.62
$str .= $i;
}
echo strlen($str) / 1024 ** 2 . ' Mb' . PHP_EOL; // Занимаемая память, примерно равна данному значению, плюс пару Кб для бинарной информации
// Каждый эксперимент будет проведе 1000 раз и из него получим среднее значение
$beforeCycle = [];
$insideInCycle = [];
for ($i = 0; $i < 1000; $i++){
echo $i;
// Подсчет до начала цикла
$start = microtime(true);
$len = strlen($str);
for ($j = 0; $j < $len; $j++){
$a = $str[$j]; // любое действие просто для эксперимента
}
$finish = microtime(true);
$beforeCycle[] = $finish - $start;
echo ' | ' . $finish - $start;
//Подсчет внутри цикла
$start = microtime(true);
for ($j = 0; $j < strlen($str); $j++){
$a = $str[$j]; // любое действие просто для эксперимента
}
$finish = microtime(true);
$insideInCycle[] = $finish - $start;
echo ' | ' . $finish - $start . PHP_EOL;
}
echo array_sum($beforeCycle) / count($beforeCycle) . PHP_EOL; // 1.0557837963104
echo array_sum($insideInCycle) / count($insideInCycle); // 1.1919854850769