Fiber (PHP 8.1+) — это встроенный в язык механизм приостановки и возобновления выполнения функции без расширений вроде Swoole. Сам по себе Fiber не даёт параллелизма или неблокирующего I/O — он только управляет точкой возврата, а сетевые и файловые операции без блокировки сверху добавляют библиотеки планировщика, такие как Revolt или amphp.
Что Fiber делает, а что нет
Fiber оборачивает функцию в объект, который можно запустить, приостановить изнутри и возобновить снаружи, передавая значения в обе стороны. Это низкоуровневый примитив — переключение контекста без создания нового процесса или потока ОС, в пределах одного процесса PHP.
Fiber сам не делает сетевой вызов неблокирующим: без цикла событий вокруг него suspend просто останавливает выполнение до явного resume. Именно такой цикл событий (Revolt, amphp) превращает набор Fiber в реальный асинхронный код с несколькими задачами одновременно.
Минимальный пример: start, suspend, resume
Ниже — буквально вся механика Fiber без библиотек планировщика: функция приостанавливается внутри, а код снаружи решает, когда её возобновить и что передать обратно.
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('started');
echo $value, PHP_EOL;
});
$fiber->start();
$fiber->resume('resumed');Чем это отличается от корутин Swoole
Swoole даёт готовый цикл событий, неблокирующий ввод-вывод на уровне расширения и собственный HTTP-сервер — всё это разобрано в статье про Swoole и RoadRunner. Fiber — это только базовый кирпич языка, на котором библиотеки уровня Revolt строят такой же цикл событий без C-расширения, жертвуя частью производительности ради переносимости на любой хостинг с PHP 8.1 и выше.
- Нужна обёртка-планировщик (Revolt, amphp) — без неё Fiber не даёт конкурентности
- Нет встроенного неблокирующего клиента для MySQL или Redis, как в Swoole
- Работает в любом окружении CLI и FPM без установки расширения
- Переключение между Fiber дешевле создания потока, но дороже вызова обычной функции
- Исключения внутри Fiber нужно явно перехватывать при resume, иначе они теряются
Где Fiber действительно полезен на практике
Fiber годится там, где скрипт выполняет несколько независимых операций ожидания — несколько HTTP-запросов к внешним API, несколько запросов к очереди — и запущен в обычном PHP-процессе CLI, а не под Swoole. Разница между запуском через CLI и через FPM для таких длительных скриптов разобрана в статье про PHP в cron.
Fiber не заменяет очередь сообщений: он ускоряет ожидание внутри одного процесса, но не даёт изоляции от падения процесса и не перезапускает задачу сам. Надёжный перезапуск воркеров очередей через Supervisor остаётся отдельной темой, разобранной в статье про очереди PHP и Supervisor.
Таблица: подходы к конкурентности в PHP
Таблица сравнивает механизмы, а не скорость — конкретная разница в производительности зависит от задачи и должна быть измерена отдельно.
| Подход | Нужно расширение | Типичная задача |
|---|---|---|
| Обычный блокирующий PHP | нет | простой скрипт, одна задача за раз |
| Fiber + Revolt или amphp | нет | несколько независимых HTTP-запросов в CLI-скрипте |
| Swoole | да | долгоживущий сервер с корутинами и своим HTTP-сервером |
| RoadRunner | нет, отдельный бинарник | долгоживущие PHP-воркеры за Go-сервером |
Частые вопросы
Нужно ли менять код на Fiber ради ускорения обычного сайта?
Нет: если сайт обслуживается через PHP-FPM с одним запросом на процесс, Fiber ничего не ускоряет без цикла событий вокруг него и без перехода на долгоживущие воркеры.
Можно ли использовать Fiber вместе с Swoole?
Да, Swoole сам построен на похожей идее переключения контекста и предоставляет собственные корутины, которые во многих версиях совместимы с кодом на Revolt внутри одного процесса.
Что происходит с исключением внутри Fiber, если его не перехватить?
Исключение всплывает при следующем вызове resume на этом Fiber, а не в момент выброса внутри функции — если вызывающий код не оборачивает resume в try-catch, исключение прерывает выполнение так же, как обычное необработанное исключение.