- PVSM.RU - https://www.pvsm.ru -
Перевод данной статьи подготовлен специально для студентов курса «Backend разработчик на PHP» [1].

В PHP 7.4 добавлена предварительная загрузка — возможность, которая позволяет значительно повысить производительность кода.
О предзагрузке в двух словах.
Да, предварительная загрузка основывается на opcache, но это не совсем одно и то же. Opcache берет исходные файлы PHP, компилирует их в опкоды, после чего сохраняет скомпилированные файлы на диск.
Опкоды можно считать низкоуровневым представлением вашего кода, которое легко интерпретируется во время выполнения. Таким образом, opcache позволяет пропустить этап трансляции исходных файлов в то, что, собственно, и необходимо интерпретатору PHP во время выполнения. Заметная экономия!
Тем не менее можно сэкономить еще больше. Скомпилированные при помощи opcash файлы ничего не знают о других файлах. Если у вас есть класс А, являющийся расширением класса B, их все равно нужно будет связать во время выполнения. Кроме того, opcache проверяет, изменились ли исходные файлы, и при обнаружения изменений аннулирует их кэши.
И тут на помощь приходит предварительная загрузка: она не только компилирует исходные файлы в опкоды, но и связывает зависимые классы, трейты и интерфейсы. Она сохраняет такой «скомпилированный» фрагмент исполняемого кода (то есть кода, который может использовать PHP-интерпретатор) в памяти.
Когда на сервер поступает запрос, тот может использовать части кодовой базы, которая уже была загружена в память, без лишних затрат времени.
Для корректной предварительной загрузки разработчик должен указать серверу, какие файлы нужно загрузить. Это делается с помощью простого PHP-скрипта, так что бояться нечего.
Ничего сложного.
opcache.preload.opcache_compile_file() из скрипта предварительной загрузки.Допустим, вы хотите предварительно загрузить какой-нибудь фреймворк. Пусть это будет Laravel. В этом случае ваш скрипт должен просмотреть все PHP-файлы в директории vendor/laravel и добавить их поочередно.
Вот как вы можете подключить этот скрипт в php.ini:
opcache.preload=/path/to/project/preload.php
А вот пример реализации:
$files = /* Массив файлов, которые вы хотите предварительно загрузить */;
foreach ($files as $file) {
opcache_compile_file($file);
}
Вместо opcache_compile_file вы можете использовать include. Однако, похоже, здесь не обошлось без бага [2], так как на момент написания статьи второй вариант не сработал.
Появилось предупреждение Can't preload unlinked class? Дело в том, что перед предзагрузкой файлов нужно также предварительно загрузить их зависимые объекты — интерфейсы, трейты и родительские классы.
Если возникнут какие-либо проблемы с зависимостями классов, то вас предупредят об этом при запуске сервера:
Can't preload unlinked class
IlluminateDatabaseQueryJoinClause:
Unknown parent
IlluminateDatabaseQueryBuilder
Обратите внимание, что opcache_compile_file() только распарсит файл, но не выполнит его. Это значит, что если у класса есть зависимости, которые не были предварительно загружены, то и сам класс не может быть предварительно загружен.
Это не критично: сервер будет работать, как обычно, но в вашем распоряжении не будет всех файлов, которые вы хотели предварительно загрузить.
Именно поэтому нужно внимательнее подбирать файлы для предварительной загрузки, чтобы избежать проблем с зависимостями. Делать это вручную — задача неблагодарная и трудоемкая, так что разработчики уже трудятся над автоматизированными решениями.
Наиболее перспективное автоматизированное решение готовят разработчики composer, который уже используется в большинстве современных PHP-проектов.
Сейчас ребята работают над возможностью настройки предварительной загрузки в composer.json, которая в свою очередь сгенерирует вместо вас файл предварительной загрузки. Как и сама предварительная загрузка, эта функция все еще находится на стадии разработки. Следить за развитием событий можно здесь [3].
К счастью, вам не придется вручную настраивать файлы предварительной загрузки, если вы этого не хотите, — composer сможет сделать это за вас.
Есть еще два важных момента, о которых должен помнить разработчик при использовании предварительной загрузки.
Вы уже знаете, что нужно создать запись в php.ini, чтобы предварительная загрузка сработала. Это значит, что если вы используете shared-хостинг, то не сможете настраивать PHP как вздумается.
На практике вам понадобится выделенный (виртуальный) сервер, чтобы оптимизировать предварительно загруженные файлы для отдельного проекта. Имейте это в виду.
Также помните, что вам нужно будет перезапускать сервер (если вы используете php-fpm, этого достаточно) каждый раз, когда вы захотите перезагрузить файлы в памяти. Для большинства это очевидно, но не будет лишним напомнить.
Теперь перейдем к самому важному вопросу: действительно ли предварительная загрузка повышает производительность?
Разумеется! Бен Морел (Ben Morel) поделился результатами сравнительного тестирования, которые можно найти в той же теме по composer [4], на которую мы ссылались выше.
И еще, что интересно. При желании вы можете предварительно загрузить только так называемые hot classes — классы, которые часто используются в вашей кодовой базе. Тесты Бена Морела показывают, что загрузка всего около 100 таких классов обеспечивает более высокий рост производительности, чем предварительная загрузка всего сразу. В первом случае производительность повышается на 17 %, во втором — на 13 %.
Разумеется, выбор классов для предварительной загрузки зависит от конкретного проекта. Разумнее всего для начала просто предварительно загрузить как можно больше. Если же вам так важны эти несколько процентов разницы в производительности, то придется контролировать код во время выполнения.
Все эти операции, конечно же, можно автоматизировать, и это, вероятно, будет сделано в будущем.
Сейчас важно, что в composer будет добавлена поддержка предзагрузки, что избавит от необходимости самостоятельно создавать файлы для нее. Эту функцию очень легко настроить на сервере при условии, что он находится в полном вашем распоряжении.
________________________________________
Будете ли вы использовать предварительную загрузку в новой версии PHP 7.4? Появились мысли или замечания? Напишите мне в Twitter [5] или по электронной почте [6].
Традиционно ждем ваши комментарии и плюсы, если считаете статью интересной :-)
Автор: MaxRokatansky
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/326556
Ссылки в тексте:
[1] «Backend разработчик на PHP»: https://otus.pw/3w1W/
[2] бага: https://bugs.php.net/bug.php?id=78240
[3] здесь: https://github.com/composer/composer/issues/7777
[4] теме по composer: https://github.com/composer/composer/issues/7777#issuecomment-440268416
[5] Twitter: https://twitter.com/brendt_gd
[6] электронной почте: mailto:brendt@stitcher.io
[7] Источник: https://habr.com/ru/post/463117/?utm_campaign=463117&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.