Подписка

Быстрый код

Этот пост можно также назвать "Техники написания кода", так как приведенные ниже советы хорошо использовать не только в проектах которые разрабатываются для работы в условиях сильной нагрузки, но и для любых PHP приложений.
В основном слабым местом являются запросы к внешним источникам данных, поэтому большинство приемов заключаются уменьшении их количества кешированием данных.

0. Избегать медленных языковых конструкций

  • многомерные массивы
  • при итерации массива, вычислять его значение на каждом шагу (стыдно, но очень распространенная ошибка):
    Вместо:
    for ($i=0; $i < count($arr); $i++)
    Сначала вычисляем размер и только после этого бегаем по циклу:
    $size = count($arr);
    for ($i=0; $i < $size; $i++)
    
  • Hash массивы и т.д
Больше информации можно найти на phpbench.com.

1. Lazy loading

Lazy loading - загрузка данных только по требованию с последующим кешированием. Данный метод подходит для не изменяющихся данных, которые получаются из внешних источников. Пример:
class MyEntity {
     protected $someRating = null;
     public function getRating() {
          if ($this->someRating == null) {
               $this->someRating = externalSource::load();
          }
          return $this->someRating;
     }
}
Как видно из примера, мы загружаем данные только раз, а при последующих обращениях будут использоваться полученные ранее.

2. Singleton для повторного использования глобальных объектов

Singleton - паттерн проектирования ПО который используется когда нужно иметь только один экземпляр объекта, например соединение с базой данных, глобальный реестр и др. Пример реализации из документации PHP:
class Example {
     private static $instance;
     private $count = 0;

     private function __construct() {}

     public static function getInstance() {
          if (!isset(self::$instance)) {
               $className = __CLASS__;
               self::$instance = new $className;
          }
          return self::$instance;
     }

     public function increment() {
          return $this->count++;
     }

     public function __clone() {
          trigger_error('Clone is not allowed.', E_USER_ERROR);
     }

     public function __wakeup() {
          trigger_error('Unserializing is not allowed.', E_USER_ERROR);
     }
}
При первом выполнении Example::getInstance() будет создан экземпляр класса Example, который будет возвращаться при последующих вызовах.

3. Кешировать данные в память

Тут можно говорить много, поэтому опишу кратко, а в будущем, напишу несколько статей с более детальным описанием техник и методов. Кратко говоря - берем данные, которые изменяются с небольшой частотой и сохраняем их в память, в удобном формате. При следующем запросе, если данные не поменялись, используем сохраненные в памяти.
Например, нужно вывести диаграмму статистики использования сайта за вчерашний день, и сделать это можно только при помощи сложного запроса. Очевидно, что на протяжении дня, данные за предыдущий день изменяться не будут, поэтому результат можно запросто кешировать, минуя сложный запрос.

4. Поручать обработку данных SQL серверу

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

5. Кешировать промежуточный код (opcode caching)

Так как PHP - интерпретируемый язык, при каждом запросе, скрипт заново компилируется в байт-код и только затем исполняется. Чтобы оптимизировать это процесс используются приложения (например APC или eAccelerator) , которые кешируют байт-код в память, позволяя избавиться от этапа компиляции при каждом запуске.

6. Пользоваться профайлером

Наверняка это самый полезный совет - ввести себе в привычку время от времени прогонять код в профайлере, для выявления медленных участков.

Статьи по теме:

  1. Профилирование кода при помощи xDebug
  2. Советы от Гугла об оптимизации php приложений
Вопросы и комментарии приветствуются.

Если пост понравился, можете нажать на гугловский аналог Like, мне будет приятно.
@kkooler

@kkooler

Занимаюсь разработкой высоконагруженных проектов и распределенных систем на PHP.
В свободное время разрабатываю нано-проекты:

Следить за блогом

RSS канал Twitter