PHP Файберы: Что это такое и где их использовать

Источник: «PHP Fibers: What They Are and Where To Use»
Файберы представленные в PHP представляют собой элегантный способ имитации параллельной работы. Узнайте больше о том, чем они отличаются от потоков и сопрограмм.

PHP эволюционирует от языка программирования для скрипт-кидди, который фокусируется на создании некоторого HTML-кода на стороне сервера, до мощного и современного языка программирования. В то время как PHP рендерил динамические веб-сайты для Web2.0 и отправлял их клиенту для отображения в браузере, современные подходы ушли от этого. Это произошло не только благодаря тому, что изменилось определение динамического — благодаря множеству мощных JavaScript фреймворков — но и потому, что природа веб-приложений стала гораздо более широкой и сложной.

Из того, что я могу наблюдать, PHP всё больше и больше становиться бэкэнд-фреймворком. Конечно, вы всё ещё можете выводить HTML, но с точки зрения микросервисов или серверных приложений это больше не нужно или плохо масштабируется. Итак, мы получаем кучу новых и оптимизированных функций. Одна из них Fibers.

Параллелизм: Потоки (threads), Сопрограммы (coroutines), Файберы (fibers)

Перво-наперво: PHP не поддерживает многопоточность, как, например, Java. Потоки (threads) планируются операционной системой, не имеют эксклюзивной памяти, а вместо этого совместно используют память основного процесса, и каждый поток может выполнять отдельный путь кода и имеет свой собственный счётчик программ, стек и состояние регистра. Конечно, основной процесс может иметь более одного потока. Потоки могут быть трудными для чтения/понимания (особенно для начинающих) и могут привести к условиям гонки (race conditions), когда два или более потока получают доступ к общим ресурсам или памяти, несинхронизированным или непредсказуемым образом.

Сопрограммы (coroutines) отличаются от потоков тем, как они планируются, и уровнем контроля над выполнением, который они обеспечивают. В то время как потоки планируются упреждающе, что означает, что операционная система или среда выполнения решают, когда переключаться между ними. Сопрограммы планируются совместно, что означает, что они должны явно передавать управление другим сопрограммам, чтобы позволить им выполняться.

Файберы (fibers) похожи на сопрограммы в том, что они обеспечивают эффективное параллельное выполнение нескольких потоков кода. Однако в то время как сопрограммы обычно управляются кодом приложения, файберы управляются средой выполнения. Кроме того, файберы обычно используются для лёгкого параллелизма, такого как HTTP-запросы, соединение с базой данных и т.д. Файберы также известны как Green Threads, потому что они позволяют избежать проблем, упомянутых выше в отношении потоков. Чистота заключается в том, что вы работаете с одним и тем же основным процессом, а не порождаете под процессы.

Файберы в PHP

Файберы (Fiber) были добавлены в PHP с версией 8.1 и, как упоминалось выше, в них нет параллелизма, как у потоков, и всё происходит по-прежнему в основном процессе. Основной поток выполнения и Fiber не происходят одновременно. Fiber может быть запущен только основным потоком выполнения, и пока он работает, это единственное, что выполняется. Если есть другие файберы, они не будут выполняться и будут "приостановлены" (suspended).

Возьмём конкретный пример: представьте, что у вас есть два задания, реализованных в виде файберов. Первый занимает около 60 секунд, второй только 2. Планировщик заданий, выполняющий файберы, поймёт, что первое задание занимает слишком много времени. Приостановит его (это означает, что вся операция, независимо от того, что это, будет приостановлена) и продолжит второе задание. После завершения второго задания планировщик возобновит первое задание и продолжит работу с того места, где оно было остановлено.

Что приводит нас к сути: файберы — элегантный способ сделать такие вещи, как HTTP-запросы, извлечение данных из базы данных и другие операции связанные с вводом-выводом, работать более гладко, а другие, гораздо менее тяжёлые операции выполняются быстрее. Обратите внимание, это не означает, что всё делается параллельно или асинхронно. Это всё ещё один процесс, и если что-то обрабатывается, всё остальное приостанавливается.

Начиная с версии 5.5, PHP предоставляет родственную концепцию под названием генераторы. Генераторы — это удобный способ вернуть итерируемые объекты, которые можно использовать для ленивой генерации последовательности значений. Что может быть более эффективным с точки зрения использования памяти, чем предварительное создание всей последовательности.

По сравнению с генераторами файберы гораздо более читабельны и гибки. Но файберы не идут ни в какое сравнение с, например, сопрограммами в Kotlin. Чтобы иметь реальный параллелизм/асинхронность PHP, предстоит пройти долгий путь. Файберы — хороший шаг, скорее начало, точно не конец и даже не средина.

Заключение

После всего прочитанного должен добавить, что меня это немного разочаровывает. Конечно, я не ожидал больших шагов к асинхронному PHP только с одной функцией или только в релизе. Но всё же, немного большего. Это не просто функция, актуальная для таких фреймворков, как ReactPHP или AMP, которые должны быть параллельными и иметь свои способы асинхронности до PHP 8.1.

Однако я не хочу довольствоваться только теорией. Вот почему я проведу несколько тестов производительности и рефакторинг существующего кода в продакшене для использования файберов.

Мы запускаем планировщик заданий, который выполняет некоторые тяжёлые задачи — подключения к базе данных/SMTP/HTTP — это лишь некоторые из них. В настоящее время они работают синхронно в цикле. Вот с чего я хотел бы начать и попробовать файберы: я хочу провести рефакторинг планировщика заданий, чтобы использовать файберы. Результаты, скорее всего будут доступны в блоге Keestash

Дополнительные материалы

Предыдущая Статья

Symfony 6.3 Добавлены новые возможности

Следующая Статья

Слепая SQL-инъекция