Оптимизация РНР-сценариев. Часть 2. Построение профиля программы

Секрет поиска оптимальных вариантов — построение профиля программы.

В процессе оптимизации и ускорения кода, вне зависимости от того, на каком языке программирования написан код, единственно важной задачей является поиск «узких мест» (bottleneck) в приложении. Ведь если вы не знаете, что именно является причиной замедления работы приложения (поиск этой причины называется профилированием, или построением профиля), справиться с проблемой будет невозможно.

Несмотря на существование большого количества профессиональных инструментальных средств, предназначенных для профилирования приложений, способы, на основе которых строится процесс оптимизации, можно реализовать с помощью самого простого РНР-сценария (исключение могут составлять интенсивно используемые приложения). Для удобства восприятия материала внизу предоставлен код класса, который можно использовать в качестве шаблона для решения основных задач профилирования. Этот сценарий будет использоваться для профилирования всех способов оптимизации, о которых будет говориться дальше.

Базовый профилировщик РНР

<?php
set_time_limit(0);
class simple_profiler
{
  private $start_time;
  private function get_time() (
    list($usec, $seconds) = explode(" ", microtime());
    return ((float)$usec + (float)$seconds);
  }
  function start_timer() {
    $this--->start_time = $this->get_time();
  }

  function end_timer() {
   return ($this->get_time() - $this->start_time);
  }
 }

 $timer = new simple_profiler();
  * Вставьте здесь постоянный код инициализации

 $timer->start_timer(); // запускаем таймер
 /**********************************
  * Вставьте здесь код для метода #1
 <em>
 $old_time = $timer->end_timer(); // останавливаем таймер
 $timer->start_timer(); // запускаем таймер
 * Вставьте здесь код для метода #2

 $new_time = $timer->end_timer(); // останавливаем таймер
 echo "Метод #1 выполнялся $old time секунд.\n";
 echo "Метод #2 выполнялся $old_time секунд.\n\n";
 if($old_time > $new_time) {
 $percent - number_format(100 - (($new_time / $old_time) * 100), 2);
 echo "Метод #2 был быстрее метода #1 на $percent%\n";
 } else {
 $percent = number_format(100 - (($old_time / $new_time) * 100), 2);
 echo "Метод #1 был быстрее метода #2 на $percent%\n";
 }
 ?>

Выше был определен простой класс, подходящий для большинства задач по профилированию программ — simple_profiler. С функциональной точки зрения код для построения профиля представляет собой ни что иное, как высокоточный измеритель времени, которое отводится на выполнение определенного сегмента РНРкода. Остальная часть сценария служит в качестве шаблона, который можно использовать для сравнения двух различных способов, применяемых для выполнения одной и той же задачи, чтобы определить, какой из них выполняется быстрее.

Данный шаблонный сценарий имеет три сегмента, представляющие для нас интерес (эти сегменты обозначаются комментариями-заполнителями). Первый сегмент является сегментом инициализации, в котором удобно инициализировать части сценария, не участвующие в профилировании. В частности, этот сегмент будет полезен для создания фиктивных данных (если изучается обработка данных), включая файлы и прочее. Второй и третий сегменты служат в качестве заполнителей для самого изучаемого кода. Между этими двумя сегментами нет особой разницы за исключением того, что в каждом из них должен быть реализован отличающийся способ выполнения одной и той же задачи.

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