dr.Brain

doctor Brain

мир глазами веб-разработчика

Предварительная загрузка в PHP 7.4

один из вариантов реализации прелоадера в PHP 7.4

dr.Brain

время чтения 3 мин.

Photo by Brandless on Unsplash

Не так давно один из представителей команды разработчиков Composer Сэлдак (Seldaek) убил все наши надежды на быструю предварительную загрузку проектов с помощью пакетного менеджера.

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

С чем связана такая позиция? Дело в том, что в PHP предварительная загрузка является проблемой развертывания проекта, но не проблемой зависимостей. Чтобы заставить прелоад работать, необходимо внести изменения в php.ini, а сделать это может только сам разработчик.

А вот и хорошая новость: такое ограничение не сможет остановить наше желание реализовать прелоад для своих проектов.

Предварительная загрузка и исходные данные

Если Вам нужно готовое решение, добро пожаловать в репозитарий. Но, если Вы хотите узнать КАК это работает, продолжайте чтение.

Предварительная загрузка (preloading) может стать хорошим инструментом для значительного увеличения производительности веб-приложений, не требуя внесения значительных изменений в проект. Вот так: просто и незатратно.

Следует понимать, что основной вопрос не в том, КАК осуществить предварительную загрузку, а в том, ЧТО загружать. Предварительная загрузка всего фреймворка и множества файлов очень быстро израсходует всю свободную память. Это означает, что метод сплошной загрузки не подходит, как минимум, для крупных проектов.

Какова же разумная стратегия? Полагаю - это предварительная загрузка только наиболее востребованных файлов. Остается узнать, что это за файлы. По каким критериям они будут отбираться?

К счастью, Opcache, благодаря opcache_get_status() дает нам информацию о файлах - “хитах”. С помощью этой функции, мы получаем весьма нужные данные: к каким файлам в проекте идут наиболее частые обращения, сколько памяти используют эти файлы во время работы приложения.

Неделя - рекомендуемый период для сбора данных. Это варьируемая величина, которая зависит от особенностей приложения. Главная цель - собрать достаточное количество хитов. Полагаю, Вы поняли основной принцип.

Хорошая идея: создать список предварительной загрузки, только для часто используемых файлов. И вот, для этих целей уже существует пакет.

Знакомьтесь… Прелоадер

Этот пакет автоматически создает список предварительной загрузки для Вашего приложения. С помощью Opcache он собирает исходные данные и сортирует список файлов, начиная с самых “популярных”. Список создается, пока не будет достигнут установленный лимит памяти.

Размышляя о том, какую стратегию использовать при отборе файлов, наиболее разумным выглядит выбор всех доступных файлов до достижения установленного предела памяти (по умолчанию это 32 мегабайта). Выбранные файлы сортируются по частоте использования (от большего значения к меньшему), из списка автоматически исключаются файлы самого пакета предварительной загрузки.

Что мы получаем в результате? Для часто подключаемых файлов производительность PHP вырастет.

Как это использовать? Например, поместите Composer Autoloader вместе со скриптом прелоадера:

use DarkGhostHunter\Preloader\Preloader;

Preloader::make()
    ->autoload('vendor/autoload.php')
    ->output('preload.php')
    ->generate();

Конечно, Вам решать как использовать возможности прелоадера, вышеприведенный код лишь отражает суть. Вы можете даже случайным образом переформировывать список, полагаясь, например, на данные одного из 100 запросов:

use DarkGhostHunter\Preloader\Preloader;
Preloader::make()
    ->whenOneIn(100)
    ->autoload('vendor/autoload.php')
    ->output('preload.php')
    ->overwrite()
    ->generate();

В результате, получается скрипт предварительной загрузки, готовый для вставки в Ваш php.ini:

<?php
/**
 * This file is generated automatically by Preloader.
 *
 * This script uses Composer Autoload file and `require_once` to preload the files in this
 * list. Add this file to your `php.ini` in `opcache.preload` to preload this list into
 * PHP at startup. Additionally, this file also includes information about Opcache.
 *
 *
 * Add (or update) this line in `php.ini`:
 *
 * opcache.preload=/www/app/vendor/preload.php
 *
 * --- Config ---
 * Generated at: 2019-11-20 15:20:49 UTC
 * Opcache
 *     - Used Memory: 130585 B
 *     - Free Memory: 294896 B
 *     - Wasted Memory: 347764 B
 *     - Cached files: 2675
 *     - Hit rate: 94%
 *     - Misses: 542
 * Preloader config
 *     - Memory limit: 32 MB
 *     - Overwrite: false
 *     - Files excluded: 0
 *     - Files appended: 0
 */

require_once '/www/app/vendor/autoload.php';

$files = [
    '/www/app/ClassFoo.php',
    '/www/app/ClassBar.php',
    '/www/app/ClassBaz.php',
    '/www/app/ClassQuz.php',
    '/www/app/ClassQux.php',
    '/www/app/vendor/author/package/src/Example.php',
    // ...
];

foreach ($files as $file) {
    require_once $file;
}

Вот собственно и все: darkghosthunter/preloader


Спасибо за внимание.


Перевод статьи Italo Baeza “Preloading your PHP 7.4 project in one line”

Новые публикации

Далее

Категории

О нас

Frontend & Backend. Статьи, обзоры, заметки, код, уроки.