Swoole на практиці: реальні вимірювання

Swoole — це розширення PHP, написане на C, що надає цикл подій, корутини та асинхронний I/O. Це єдина зріла реалізація корутинної моделі в екосистемі PHP з багаторічним досвідом у продакшні.

Нижче наведено збірку реальних вимірювань: продакшн-кейси, незалежні бенчмарки та дані TechEmpower.

Два джерела підвищення продуктивності

Перехід від PHP-FPM до Swoole забезпечує дві незалежні переваги:

  1. Stateful середовище виконання — застосунок завантажується один раз і залишається в пам’яті. Зникають накладні витрати на повторну ініціалізацію (autoload, DI-контейнер, конфігурація) при кожному запиті. Цей ефект дає виграш навіть без I/O.

  2. Конкурентність корутин — поки одна корутина чекає відповіді від БД або зовнішнього API, інші обробляють запити на тому ж ядрі. Цей ефект проявляється тільки за наявності I/O і вимагає використання асинхронних клієнтів (корутинний MySQL, Redis, HTTP-клієнт).

Більшість публічних бенчмарків не розділяють ці два ефекти. Тести без БД (Hello World, JSON) вимірюють лише ефект stateful. Тести з БД вимірюють суму обох, але не дозволяють ізолювати внесок корутин.

Кожен розділ нижче вказує, який ефект переважає.

1. Продакшн: Appwrite — міграція з FPM на Swoole (+91%)

Що вимірюється: stateful середовище виконання + конкурентність корутин. Appwrite — це I/O-проксі з мінімальною CPU-роботою. Виграш забезпечується обома факторами, але ізолювати внесок корутин з публічних даних неможливо.

Appwrite — це Backend-as-a-Service (BaaS) з відкритим кодом, написаний на PHP. Appwrite надає готовий серверний API для типових задач мобільних та веб-застосунків: автентифікація користувачів, керування базою даних, зберігання файлів, хмарні функції, push-сповіщення.

За своєю природою Appwrite — це чистий I/O-проксі: майже кожен вхідний HTTP-запит перетворюється на одну або кілька I/O-операцій (запит до MariaDB, виклик Redis, читання/запис файлу), з мінімальними власними CPU-обчисленнями. Такий профіль навантаження витягує максимальну користь з переходу на корутини: поки одна корутина чекає відповіді від БД, інші обробляють нові запити на тому ж ядрі.

У версії 0.7 команда замінила Nginx + PHP-FPM на Swoole.

Умови тестування: 500 одночасних клієнтів, 5 хвилин навантаження (k6). Усі запити до ендпоінтів з авторизацією та контролем зловживань.

Метрика FPM (v0.6.2) Swoole (v0.7) Зміна
Запитів на секунду 436 808 +85%
Загальна кількість запитів за 5 хв 131 117 242 336 +85%
Час відповіді (нормальний) 3,77 мс 1,61 мс −57%
Час відповіді (під навантаженням) 550 мс 297 мс −46%
Частка успішних запитів 98% 100% Без таймаутів

Загальне покращення, заявлене командою: ~91% за сукупністю метрик.

Джерело: Appwrite 0.7: 91% boost in API Performance (DEV.to)

2. Продакшн: IdleMMO — 35 мільйонів запитів на день на одному сервері

Що вимірюється: переважно stateful середовище виконання. Laravel Octane запускає Swoole в режимі «один запит — один воркер», без мультиплексування I/O корутинами всередині запиту. Приріст продуктивності забезпечується тим, що Laravel не перезавантажується на кожному запиті.

IdleMMO — це PHP-застосунок (Laravel Octane + Swoole), MMORPG з 160 000+ користувачами.

Метрика Значення
Запитів на день 35 000 000 (~405 req/s у середньому)
Потенціал (оцінка автора) 50 000 000+ req/день
Сервер 1 × 32 vCPU
Воркери Swoole 64 (4 на ядро)
Затримка p95 до налаштування 394 мс
Затримка p95 після Octane 172 мс (−56%)

Автор зазначає, що для менш CPU-інтенсивних застосунків (не MMORPG) той самий сервер міг би обробити значно більше запитів.

Джерело: From Zero to 35M: The Struggles of Scaling Laravel with Octane

3. Бенчмарк: PHP-FPM проти Swoole (BytePursuits)

Що вимірюється: тільки stateful середовище виконання. Тест повертає JSON без звернення до БД чи зовнішніх сервісів. Конкурентність корутин тут не задіяна — немає I/O, який можна було б виконувати паралельно. Різниця у 2,6–3x повністю обумовлена тим, що Swoole не перестворює застосунок на кожному запиті.

Незалежний бенчмарк на мікрофреймворку Mezzio (JSON-відповідь, без БД). Intel i7-6700T (4 ядра / 8 потоків), 32 ГБ RAM, wrk, 10 секунд.

Конкурентність PHP-FPM (req/s) Swoole BASE (req/s) Різниця
100 3 472 9 090 2,6x
500 3 218 9 159 2,8x
1 000 3 065 9 205 3,0x

Середня затримка при 1000 одночасних:

Критичний момент: починаючи з 500 одночасних з’єднань, PHP-FPM почав втрачати запити (73 793 помилки сокетів при 500, 176 652 при 700). Swoole мав нуль помилок на всіх рівнях конкурентності.

Джерело: BytePursuits: Benchmarking PHP-FPM vs Swoole

4. Бенчмарк: з базою даних (kenashkov)

Що вимірюється: набір тестів з різними ефектами.

  • Hello World, Autoload — чистий stateful (без I/O).
  • SQL-запит, реальний сценарій — stateful + корутини.
  • Swoole використовує корутинний MySQL-клієнт, що дозволяє обслуговувати
  • інші запити під час очікування відповіді від БД.

Більш реалістичний набір тестів: Swoole 4.4.10 проти Apache + mod_php. ApacheBench, 100–1000 одночасних, 10 000 запитів.

Сценарій Apache (100 конк.) Swoole (100 конк.) Різниця
Hello World 25 706 req/s 66 309 req/s 2,6x
Autoload 100 класів 2 074 req/s 53 626 req/s 25x
SQL-запит до БД 2 327 req/s 4 163 req/s 1,8x
Реальний сценарій (кеш + файли + БД) 141 req/s 286 req/s 2,0x

При 1000 одночасних:

Ключове спостереження: з реальним I/O (БД + файли) різниця зменшується з 25x до 1,8–2x. Це очікувано: база даних стає спільним вузьким місцем. Але стабільність під навантаженням залишається непорівнянною.

Джерело: kenashkov/swoole-performance-tests (GitHub)

5. Бенчмарк: Symfony 7 — усі середовища виконання (2024)

Що вимірюється: тільки stateful середовище виконання. Тест без БД — корутини не задіяні. Різниця >10x пояснюється тим, що FPM створює процес на кожен запит, тоді як Swoole та FrankenPHP тримають застосунок у пам’яті та обслуговують з’єднання через цикл подій.

Тест 9 PHP-середовищ виконання з Symfony 7 (k6, Docker, 1 CPU / 1 ГБ RAM, без БД).

Середовище виконання проти Nginx + PHP-FPM (при 1000 конк.)
Apache + mod_php ~0,5x (повільніше)
Nginx + PHP-FPM 1x (базовий рівень)
Nginx Unit ~3x
RoadRunner >2x
Swoole / FrankenPHP (worker) >10x

При 1000 одночасних з’єднань Swoole та FrankenPHP у режимі worker показали на порядок вищу пропускну здатність, ніж класичний Nginx + PHP-FPM.

Джерело: Performance benchmark of PHP runtimes (DEV.to)

6. TechEmpower: Swoole — перше місце серед PHP

Що вимірюється: stateful + корутини (у тестах з БД). TechEmpower включає як JSON-тест (stateful), так і тести з кількома SQL-запитами (multiple queries, Fortunes), де корутинний доступ до БД дає реальну перевагу. Це один з небагатьох бенчмарків, де ефект корутин найбільш виразно видимий.

У TechEmpower Framework Benchmarks (Round 22, 2023) Swoole посів перше місце серед усіх PHP-фреймворків у тесті MySQL.

TechEmpower тестує реальні сценарії: серіалізацію JSON, одиничні запити до БД, множинні запити, ORM, Fortunes (шаблонізація + БД + сортування + екранування).

Джерело: TechEmpower Round 22, swoole-src README

7. Hyperf: 96 000 req/s на фреймворку Swoole

Що вимірюється: stateful середовище виконання (бенчмарк — Hello World). Hyperf повністю побудований на корутинах Swoole, і у продакшні конкурентність корутин використовується для БД, Redis та gRPC-викликів. Однак цифра 96K req/s отримана на Hello World без I/O, тобто відображає ефект stateful середовища виконання.

Hyperf — це корутинний PHP-фреймворк, побудований на Swoole. У бенчмарку (4 потоки, 100 з’єднань):

Hyperf позиціонується для мікросервісів і заявляє 5–10x перевагу над традиційними PHP-фреймворками.

Джерело: Hyperf GitHub

Підсумок: що показують реальні дані

Тип тесту FPM → Swoole Основний ефект Примітка
Hello World / JSON 2,6–3x Stateful BytePursuits, kenashkov
Autoload (stateful проти stateless) 25x Stateful Без I/O — чистий ефект збереження стану
З базою даних 1,8–2x Stateful + корутини kenashkov (корутинний MySQL)
Продакшн API (Appwrite) +91% (1,85x) Stateful + корутини I/O-проксі, обидва фактори
Продакшн (IdleMMO) p95: −56% Stateful Воркери Octane, не корутини
Висока конкурентність (1000+) Swoole стабільний, FPM падає Цикл подій Усі бенчмарки
Середовища Symfony (1000 конк.) >10x Stateful Без БД у тесті
TechEmpower (тести з БД) №1 серед PHP Stateful + корутини Множинні SQL-запити

Зв’язок з теорією

Результати добре узгоджуються з розрахунками з Ефективність IO-bound задач:

1. З базою даних різниця скромніша (1,8–2x), ніж без неї (3–10x). Це підтверджує: з реальним I/O вузьким місцем стає сама БД, а не модель конкурентності. Коефіцієнт блокування у тестах з БД нижчий, оскільки CPU-робота фреймворку порівнянна з часом I/O.

2. При високій конкурентності (500–1000+) FPM деградує, а Swoole ні. PHP-FPM обмежений кількістю воркерів. Кожен воркер — це процес ОС (~40 МБ). При 500+ одночасних з’єднань FPM досягає ліміту і починає втрачати запити. Swoole обслуговує тисячі з’єднань у десятках корутин без збільшення споживання пам’яті.

3. Stateful середовище виконання усуває накладні витрати на повторну ініціалізацію. Різниця у 25x у тесті autoload демонструє вартість перестворення стану застосунку на кожному запиті у FPM. У продакшні це проявляється як різниця між T_cpu = 34 мс (FPM) та T_cpu = 5–10 мс (stateful), що драматично змінює коефіцієнт блокування і відповідно виграш від корутин (див. таблицю в Ефективність IO-bound задач).

4. Формула підтверджується. Appwrite: FPM 436 req/s → Swoole 808 req/s (1,85x). Якщо T_cpu знизився з ~30 мс до ~15 мс (stateful), а T_io залишився ~30 мс, то коефіцієнт блокування зріс з 1,0 до 2,0, що передбачає збільшення пропускної здатності приблизно в 1,5–2x. Це збігається.

Посилання

Продакшн-кейси

Незалежні бенчмарки

Фреймворки та середовища виконання