Dati statistici per il calcolo della concorrenza

Le formule della sezione Efficienza dei task IO-bound operano su diverse grandezze chiave. Di seguito una raccolta di misurazioni reali che permettono di inserire numeri concreti nelle formule.


Elementi delle formule

Legge di Little:

\[L = \lambda \cdot W\]

Formula di Goetz:

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

Per il calcolo pratico, e’ necessario conoscere:

  1. Quante query SQL vengono eseguite per richiesta HTTP
  2. Quanto tempo impiega una query SQL (I/O)
  3. Quanto tempo richiede l’elaborazione CPU
  4. Qual e’ il throughput del server
  5. Qual e’ il tempo di risposta complessivo

1. Query SQL per richiesta HTTP

Il numero di chiamate al database dipende dal framework, dall’ORM e dalla complessita’ della pagina.

Applicazione / Framework Query per pagina Fonte
WordPress (senza plugin) ~17 Drupal Groups: How many queries per page
Symfony (Doctrine, pagina media) <30 (soglia profiler) Symfony Docs: Profiler testing
Laravel (CRUD semplice) 5–15 Valori tipici da Laravel Debugbar
Laravel (con problema N+1) 20–50+ Laravel Daily: Debug Slow Queries
Drupal (senza cache) 80–100 Drupal Groups
Magento (catalogo) 50–200+ Tipico per e-commerce complesso

Mediana per una tipica applicazione ORM: 15–30 query per richiesta HTTP.

Symfony utilizza una soglia di 30 query come limite “normale” — superata la quale, l’icona del profiler diventa gialla.

2. Tempo per query SQL (T_io per query)

Tempo di esecuzione della query sul server DB

Dati dai benchmark sysbench OLTP di Percona (MySQL):

Concorrenza Quota di query <0,1 ms 0,1–1 ms 1–10 ms >10 ms
1 thread 86% 10% 3% 1%
32 thread 68% 30% 2% <1%
128 thread 52% 35% 12% 1%

LinkBench (Percona, approssimazione del carico reale di Facebook):

Operazione p50 p95 p99
GET_NODE 0,4 ms 39 ms 77 ms
UPDATE_NODE 0,7 ms 47 ms 100 ms

Fonte: Percona: MySQL and Percona Server in LinkBench, Percona: Query Response Time Histogram

Latenza di rete (round-trip)

Scenario Round-trip Fonte
Unix-socket / localhost <0,1 ms CYBERTEC PostgreSQL
LAN, singolo data center ~0,5 ms CYBERTEC PostgreSQL
Cloud, cross-AZ 1–5 ms CYBERTEC PostgreSQL
Cross-region 10–50 ms Valori tipici

Totale: tempo completo per query SQL

Tempo completo = tempo di esecuzione lato server + round-trip di rete.

Ambiente SELECT semplice (p50) Query media (p50)
Localhost 0,1–0,5 ms 0,5–2 ms
LAN (singolo DC) 0,5–1,5 ms 1–4 ms
Cloud (cross-AZ) 2–6 ms 3–10 ms

Per un ambiente cloud, 4 ms per query media e’ una stima ben fondata.

3. Tempo CPU per query SQL (T_cpu per query)

Il tempo CPU copre: parsing del risultato, hydration delle entita’ ORM, mapping degli oggetti, serializzazione.

Benchmark diretti di questo specifico valore sono scarsi nelle fonti pubbliche, ma possono essere stimati dai dati del profiler:

Stima indiretta tramite throughput:

Symfony con Doctrine (DB + rendering Twig) elabora ~1000 req/s (Kinsta PHP Benchmarks). Questo significa tempo CPU per richiesta ≈ 1 ms. Con ~20 query SQL per pagina → ~0,05 ms CPU per query SQL.

Endpoint API Laravel (Sanctum + Eloquent + JSON) → ~440 req/s (Sevalla: Laravel Benchmarks). Tempo CPU per richiesta ≈ 2,3 ms. Con ~15 query → ~0,15 ms CPU per query SQL.

4. Throughput (λ) delle applicazioni PHP

Benchmark eseguiti su 30 vCPU / 120 GB RAM, nginx + PHP-FPM, 15 connessioni concorrenti (Kinsta, Sevalla):

Applicazione Tipo di pagina req/s (PHP 8.4)
Laravel Welcome (senza DB) ~700
Laravel API + Eloquent + Auth ~440
Symfony Doctrine + Twig ~1.000
WordPress Homepage (senza plugin) ~148
Drupal 10 ~1.400

Da notare che WordPress e’ significativamente piu’ lento perche’ ogni richiesta e’ piu’ pesante (piu’ query SQL, rendering piu’ complesso).


5. Tempo di risposta complessivo (W) in produzione

Dati da LittleData (2023, 2.800 siti e-commerce):

Piattaforma Tempo medio di risposta del server
Shopify 380 ms
Media e-commerce 450 ms
WooCommerce (WordPress) 780 ms
Magento 820 ms

Fonte: LittleData: Average Server Response Time

Benchmark industriali:

Categoria Tempo di risposta API
Eccellente 100–300 ms
Accettabile 300–600 ms
Necessita ottimizzazione >600 ms

Calcolo pratico con la Legge di Little

Scenario 1: API Laravel nel cloud

Dati di input:

Calcolo:

\[L = \lambda \cdot W = 440 \times 0.080 = 35 \text{ task concorrenti}\]

Su 8 core, sono ~4,4 task per core. Questo corrisponde al fatto che Laravel con 15 worker PHP-FPM concorrenti raggiunge gia’ 440 req/s. C’e’ margine di crescita.

Scenario 2: API Laravel nel cloud, 2000 req/s (target)

Dati di input:

Calcolo:

\[L = 2000 \times 0.080 = 160 \text{ task concorrenti}\]

PHP-FPM non puo’ gestire 160 worker su 8 core — ogni worker e’ un processo separato con ~30–50 MB di memoria. Totale: ~6–8 GB solo per i worker.

Con le coroutine: 160 task × ~4 KiB ≈ 640 KiB. Una differenza di quattro ordini di grandezza.

Scenario 3: Utilizzo della formula di Goetz

Dati di input:

Calcolo:

\[N = 8 \times \left(1 + \frac{80}{1}\right) = 8 \times 81 = 648 \text{ coroutine}\]

Throughput (tramite la Legge di Little):

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

Questo e’ il tetto teorico con pieno utilizzo di 8 core. In pratica, sara’ inferiore a causa dell’overhead dello scheduler, del GC, dei limiti del pool di connessioni. Ma anche il 50% di questo valore (4.000 req/s) e’ un ordine di grandezza superiore ai 440 req/s di PHP-FPM sugli stessi 8 core.

Riepilogo: da dove provengono i numeri

Grandezza Valore Fonte
Query SQL per richiesta HTTP 15–30 WordPress ~17, soglia Symfony <30
Tempo per query SQL (cloud) 3–6 ms Percona p50 + CYBERTEC round-trip
CPU per query SQL 0,05–0,15 ms Calcolo inverso dai benchmark di throughput
Throughput Laravel ~440 req/s (API) Benchmark Sevalla/Kinsta, PHP 8.4
Tempo di risposta e-commerce (media) 450 ms LittleData, 2.800 siti
Tempo di risposta API (norma) 100–300 ms Benchmark industriale

Riferimenti

Benchmark dei framework PHP

Benchmark dei database

Tempi di risposta dei sistemi in produzione

Profilazione PHP