Начиная с PHP 7.4.0 разрешили настройку PHP на предварительную загрузку скриптов в память модуля opcache при запуске движка. Доступ к функциям, классам, интерфейсам или трейтам (но не константам) в этих файлах станет глобальным для всех запросов; файлы не потребуется включать явно. Предзагрузка повышает удобство и производительность за счёт постоянной доступности кода для очередных запросов, но увеличивает расход памяти. Одновременно с этим, изменения в предзагруженных скриптах вступят в силу только после перезагрузки PHP-процесса, которая очистит скрипты, которые предварительно загрузили. Поэтому предзагрузку скриптов выполняют только в производственном окружении, а не в среде разработки.
Баланс между ростом производительности и расходом памяти зависит от приложения. «Предзагрузка каждого файла» выглядит как простейшая стратегия, но такая стратегия полезна не в каждом сценарии. Предзагрузка полезна, только когда процесс не изменяется от запроса к запросу. Поэтому, хотя предзагрузка и работает в CLI-скрипте при включённом модуле opcache, это бесполезно. Исключение — предварительная загрузка библиотек FFI.
Замечание: ОС Windows не поддерживает предзагрузку.
Настройка предзагрузки состоит из двух этапов и работает, только если включили модуль opcache. Сначала устанавливают значение для директивы opcache.preload в файле php.ini:
opcache.preload=preload.php
Файл preload.php — произвольный файл, который запустится один раз при старте сервера
в режиме менеджера процессов PHP-FPM, Apache-модуля mod_php и т. д. и загрузит код в постоянную память.
На серверах, которые перед переключением на непривилегированного пользователя системы запускаются
от имени root-пользователя, или если PHP запускается от имени root, что делать не рекомендуют,
пользователя системы для запуска предварительной загрузки указывают в директиве
opcache.preload_user.
Запуск предварительной загрузки от имени root по умолчанию запрещён.
В файле конфигурации PHP устанавливают значение opcache.preload_user=root,
чтобы явно разрешить такой запуск.
PHP проанализирует и загрузит в постоянную память каждый файл,
который указали в выражениях include , include_once ,
require , require_once
или в аргументе функции opcache_compile_file() в скрипте preload.php.
В следующем примере загрузится каждый файл с расширением .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.
PHP 8.1 comes with an inheritance cache that partially overlaps with what the preloading already does. If you enabled preloading on lower versions then migrated to PHP 8.1, you might want to turn off preloading and see if that comes with a performance penalty or not.There are caveats when enabling preloading, one of them being that it should be enabled via a php.ini file. Enabling it with a php-fpm pool configuration won't work, for instance, since preloading is global and not per-pool. To make sure that you successfully enabled preloading, you should check for a preload_statistics key in the output of opcache_get_status(). There should already be an opcache_statistics key, but that's something else entirely.