Статистичні дані для розрахунку конкурентності

Формули з розділу Ефективність IO-bound задач оперують кількома ключовими величинами. Нижче наведено збірку реальних вимірювань, що дозволяють підставити конкретні числа у формули.


Елементи формул

Закон Літтла:

\[L = \lambda \cdot W\]

Формула Гетца:

\[N = N_{cores} \times \left(1 + \frac{T_{io}}{T_{cpu}}\right)\]

Для практичного розрахунку необхідно знати:

  1. Скільки SQL-запитів виконується на один HTTP-запит
  2. Скільки часу займає один SQL-запит (I/O)
  3. Скільки часу займає обробка на CPU
  4. Яка пропускна здатність сервера
  5. Який загальний час відповіді

1. SQL-запити на HTTP-запит

Кількість звернень до бази даних залежить від фреймворку, ORM та складності сторінки.

Застосунок / Фреймворк Запитів на сторінку Джерело
WordPress (без плагінів) ~17 Drupal Groups: How many queries per page
Symfony (Doctrine, середня сторінка) <30 (поріг профайлера) Symfony Docs: Profiler testing
Laravel (простий CRUD) 5–15 Типові значення з Laravel Debugbar
Laravel (з проблемою N+1) 20–50+ Laravel Daily: Debug Slow Queries
Drupal (без кешу) 80–100 Drupal Groups
Magento (каталог) 50–200+ Типово для складної електронної комерції

Медіана для типового ORM-застосунку: 15–30 запитів на HTTP-запит.

Symfony використовує поріг у 30 запитів як межу «нормального» — при перевищенні іконка профайлера стає жовтою.

2. Час одного SQL-запиту (T_io на запит)

Час виконання запиту на сервері БД

Дані з бенчмарків sysbench OLTP від Percona (MySQL):

Конкурентність Частка запитів <0,1 мс 0,1–1 мс 1–10 мс >10 мс
1 потік 86% 10% 3% 1%
32 потоки 68% 30% 2% <1%
128 потоків 52% 35% 12% 1%

LinkBench (Percona, наближення до реального навантаження Facebook):

Операція p50 p95 p99
GET_NODE 0,4 мс 39 мс 77 мс
UPDATE_NODE 0,7 мс 47 мс 100 мс

Джерело: Percona: MySQL and Percona Server in LinkBench, Percona: Query Response Time Histogram

Мережева затримка (round-trip)

Сценарій Round-trip Джерело
Unix-socket / localhost <0,1 мс CYBERTEC PostgreSQL
LAN, один дата-центр ~0,5 мс CYBERTEC PostgreSQL
Хмара, cross-AZ 1–5 мс CYBERTEC PostgreSQL
Між регіонами 10–50 мс Типові значення

Підсумок: повний час одного SQL-запиту

Повний час = час виконання на сервері + мережевий round-trip.

Середовище Простий SELECT (p50) Середній запит (p50)
Localhost 0,1–0,5 мс 0,5–2 мс
LAN (один ДЦ) 0,5–1,5 мс 1–4 мс
Хмара (cross-AZ) 2–6 мс 3–10 мс

Для хмарного середовища 4 мс на середній запит — обґрунтована оцінка.

3. Час CPU на SQL-запит (T_cpu на запит)

Час CPU охоплює: парсинг результату, гідратацію сутностей ORM, маппінг об’єктів, серіалізацію.

Прямі бенчмарки саме цього значення рідко зустрічаються у відкритих джерелах, але його можна оцінити за даними профайлерів:

Непряма оцінка через пропускну здатність:

Symfony з Doctrine (БД + рендеринг Twig) обробляє ~1000 req/s (Kinsta PHP Benchmarks). Це означає час CPU на запит ≈ 1 мс. При ~20 SQL-запитах на сторінку → ~0,05 мс CPU на SQL-запит.

Laravel API endpoint (Sanctum + Eloquent + JSON) → ~440 req/s (Sevalla: Laravel Benchmarks). Час CPU на запит ≈ 2,3 мс. При ~15 запитах → ~0,15 мс CPU на SQL-запит.

4. Пропускна здатність (λ) PHP-застосунків

Бенчмарки на 30 vCPU / 120 ГБ RAM, nginx + PHP-FPM, 15 одночасних з’єднань (Kinsta, Sevalla):

Застосунок Тип сторінки req/s (PHP 8.4)
Laravel Welcome (без БД) ~700
Laravel API + Eloquent + Auth ~440
Symfony Doctrine + Twig ~1 000
WordPress Головна (без плагінів) ~148
Drupal 10 ~1 400

Зверніть увагу, що WordPress значно повільніший, оскільки кожен запит важчий (більше SQL-запитів, складніший рендеринг).


5. Загальний час відповіді (W) у продакшні

Дані LittleData (2023, 2 800 сайтів електронної комерції):

Платформа Середній час відповіді сервера
Shopify 380 мс
Середнє е-комерція 450 мс
WooCommerce (WordPress) 780 мс
Magento 820 мс

Джерело: LittleData: Average Server Response Time

Галузеві орієнтири:

Категорія Час відповіді API
Відмінно 100–300 мс
Прийнятно 300–600 мс
Потребує оптимізації >600 мс

Практичний розрахунок за законом Літтла

Сценарій 1: Laravel API у хмарі

Вхідні дані:

Розрахунок:

\[L = \lambda \cdot W = 440 \times 0.080 = 35 \text{ одночасних задач}\]

На 8 ядрах це ~4,4 задачі на ядро. Це відповідає тому, що Laravel з 15 одночасними PHP-FPM воркерами вже досягає 440 req/s. Є запас.

Сценарій 2: Laravel API у хмарі, 2000 req/s (ціль)

Вхідні дані:

Розрахунок:

\[L = 2000 \times 0.080 = 160 \text{ одночасних задач}\]

PHP-FPM не може обслужити 160 воркерів на 8 ядрах — кожен воркер це окремий процес з ~30–50 МБ пам’яті. Разом: ~6–8 ГБ лише для воркерів.

З корутинами: 160 задач × ~4 КіБ ≈ 640 КіБ. Різниця у чотири порядки.

Сценарій 3: за формулою Гетца

Вхідні дані:

Розрахунок:

\[N = 8 \times \left(1 + \frac{80}{1}\right) = 8 \times 81 = 648 \text{ корутин}\]

Пропускна здатність (за законом Літтла):

\[\lambda = \frac{L}{W} = \frac{648}{0.081} \approx 8\,000 \text{ req/s}\]

Це теоретична стеля при повному завантаженні 8 ядер. На практиці буде менше через накладні витрати планувальника, GC, ліміти пулу з’єднань. Але навіть 50% від цього значення (4 000 req/s) — це на порядок більше, ніж 440 req/s від PHP-FPM на тих самих 8 ядрах.

Підсумок: звідки беруться числа

Величина Значення Джерело
SQL-запитів на HTTP-запит 15–30 WordPress ~17, поріг Symfony <30
Час SQL-запиту (хмара) 3–6 мс Percona p50 + CYBERTEC round-trip
CPU на SQL-запит 0,05–0,15 мс Зворотний розрахунок з бенчмарків пропускної здатності
Пропускна здатність Laravel ~440 req/s (API) Бенчмарки Sevalla/Kinsta, PHP 8.4
Час відповіді е-комерції (середній) 450 мс LittleData, 2 800 сайтів
Час відповіді API (норма) 100–300 мс Галузевий орієнтир

Посилання

Бенчмарки PHP-фреймворків

Бенчмарки баз даних

Час відповіді продакшн-систем

Профілювання PHP