Начиная с PHP 7.4.0, можно настроить предзагрузку скриптов в opcache в момент старта PHP. Любые функции, классы, интерфейсы или трейты (но не константы) в этих файлах будут глобально доступны для всех запросов без необходимости их явной загрузки. Такая предзагрузка позволяет добиться больших удобства и производительности (потому, что код всегда доступен) за счёт использования большего количества памяти. Также, при внесении изменений в предзагруженные скрипты, чтобы эти изменения стали доступны, придётся перезагрузить PHP. Из этого следует, что предзагрузку имеет смысл использовать только в промышленном окружении, но не в разработческом.
Обратите внимание, что баланс повышения производительности и потребления памяти сильно зависит от вашего приложения. "Предзагрузка всего на свете" может быть простейшей стратегией, но совсем не обязательно лучшей. Также, предзагрузка будет работать только в случае, когда PHP работает в режиме обслуживания запросов без перезагрузки. Таким образом, хоть предзагрузку и можно использовать в режиме CLI с включённым opcache, но, в большинстве случаев бессмысленно. Исключением является использование предзагрузки с библиотеками FFI.
Замечание:
Предзагрузка не поддерживается в Windows.
Настройка предзагрузки состоит из двух этапов и требует включённого opcache. Для начала, настройте opcache.preload в php.ini:
opcache.preload=preload.php
preload.php - это обязательный файл, который будет запущен один раз при старте сервера
(PHP-FPM, mod_php, etc.) и который загрузит код в постоянную память. В серверах, которые запускаются от имени root
перед переключением на непривилегированного пользователя системы или если PHP запускается от имени root (не рекомендуется),
значение opcache.preload_user может указывать системного пользователя
для запуска предварительной загрузки.
Запуск предварительной загрузки от имени root по умолчанию запрещён.
Установите opcache.preload_user=root
, чтобы явно разрешить это.
В скрипте preload.php, любой файл указанный в include,
include_once, require, require_once или
opcache_compile_file() будет загружен в постоянную память. В следующем примере,
будут загружены все файлы .php в директории src, если они не содержат
Test
в имени.
<?php
$directory = new RecursiveDirectoryIterator(__DIR__ . '/src');
$fullTree = new RecursiveIteratorIterator($directory);
$phpFiles = new RegexIterator($fullTree, '/.+((?<!Test)+\.php$)/i', RecursiveRegexIterator::GET_MATCH);
foreach ($phpFiles as $key => $file) {
require_once($file[0]);
}
?>
И include и opcache_compile_file() будут работать, но при этом будут немного по разному обработаны.
A
и b.php определяет класс
B
, который является наследником A
, то opcache_compile_file() может
загрузить эти два файла в любом порядке. При использовании include, с другой стороны, a.php
должен быть загружен первым.