Начиная с 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.