Оптимизация скорости загрузки PHP классов через Composer

Разработчики composer продолжают оптимизировать его слабое место — автозугрузчик классов. В статье перевод из документации про три уровня оптимизации для ускорения работы приложения.

По умолчанию, загрузчик composer выполняется относительно быстро. Однако, согласно стандартам PSR-4 и PSR-0 необходимо проверять наличие файла в файловой системе перед его использованием. Это немного замедляет работу, однако это правило справедливо только для dev среды, потому что когда вы добавляете новый класс он может быть сразу же обнаружен и использован без обновления конфигурации автозагрузчика.

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

Именно поэтому composer предлагает несколько способов оптимизации автозагрузчика.

Уровень 1: Генерация карты классов

Как?

Есть несколько способов это сделать:

  • Добавить "optimize-autoloader": true в ваш composer.json;
  • Выполнить install или update с флагом -o или --optimize-autoloader;
  • Выполнить dump-autoload с флагом -o или --optimize;

Что произойдет?

Генерация карты классов превращает PSR-4/PSR-0 правила в правила classmap. Это несколько ускоряет работы, так как для известных классов карта вернет непосредственно путь к нему, и composer может гарантировать что класс существует и нет необходимости обращаться к файловой системе.

В PHP 5.6+ карта классов к тому же кэшируется в opcache что существенно улучшает время инициализации. Если opcache включен, то карта классов должна загружаться практически моментально.

Недостатки

У этого способа практически нету минусов. Он должен по умолчанию использоваться в production.

Разве что он не отслеживает не найденные классы, и в этом случае автозагрузчик работает по стандарту PSR-4 и начинает обращаться к файловой системе. Для решения этой проблемы существует второй уровень оптимизации и вы можете его использовать если имеете много вызовов class_existsдля классов, которых нет в вашей системе.

Уровень 2/A: Авторитетные карты классов

Как?

Есть несколько способов это сделать:

  • Добавить "classmap-authoritative": true в ваш composer.json;
  • Выполнить install или update с флагом -a или --classmap-authoritative;
  • Выполнить dump-autoload с флагом -a или --classmap-authoritative.

Что произойдет?

Во-первых автоматически включится первый уровень оптимизации.

В остальном все просто, автозагрузчик говорить что если класс не найден в карте — то его не существует и не нужно обращаться к файловой системе согласно стандарту PSR-4.

Недостатки

Эта опция позволяет автозагрузчику работать быстро всегда. Но с другой стороны это также значит, что если класс был сгенерирован в рантайме по какой-либо причине, он не будет загружен. Если ваш проект или его зависимости делают это вы можете столкнуться с ошибками вида class not found в production среде. Используйте с осторожностью.

Уровень 2/B: APCu кэш

Как?

Есть несколько способов это сделать:

  • Добавить "apcu-autoloader": true в ваш composer.json;
  • Выполнить install или update с флагом --apcu-autoloader;
  • Выполнить dump-autoload с флагом --apcu;

Что произойдет?

Эта опция добавит APCu кэш в качестве fallback’а для карты классов. Она не включает автоматически генерацию карты классов, так что нужно включать ее самому если необходимо.

Результат того найден был класс или нет всегда кэшируется в APCu и будет быстро возвращен при следующем обращении.

Недостатки

Для работы требуется APCu, который может быть недоступен в вашей системе. Также он использует память APCu для нужд автозагрузчика. Но тем не менее он безопасен в использовании и вы не будете сталкиваться с ошибками вида class not found как в уровне 2/A.

Важное примечание, что уровни 2/A и 2/B не могут использоваться совместно.