Как стать автором
Обновить

strlen выносить до начала цикла?

Когда давно, я прочитал, что для повышения производительности кода, необходимо выносить операции условий, до начала цикла. Это правило я распространил на все в том, числе и на длину строки. Т.е. предпочитал вариант:

  $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
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.