Quanto rallenta Drupal il modulo Native Observability, e come lo misuri sul tuo server

Approfondisci il progetto Native Observability
Native Observability è il modulo Drupal che registra dall'interno cosa succede a ogni richiesta. Strumentare un sito con lui costa circa 4,7 millisecondi per richiesta su una macchina e circa 7,0 su un'altra, e scende a circa 1,8 spegnendo due sottomoduli. La cifra dipende dal server: la tua la ottieni con drush no:overhead:measure.

Quanto rallenta Drupal il modulo Native Observability?

Native Observability (si apre in una nuova scheda) è il modulo Drupal che registra dall'interno cosa succede a ogni richiesta, e strumentare un sito con lui costa circa 4,7 e circa 7,0 millisecondi per richiesta sulle due macchine dove l'ho misurato. Stesso codice, stessa versione, stesso comando di misura, due numeri che differiscono del 48%.

Cosa faccia il modulo e come sia costruito sta nella scheda del progetto; qui si parla soltanto di quanto costa e di come si misura.

Il primo è pubblicato nella documentazione del modulo (si apre in una nuova scheda), che ne dichiara le condizioni e la provenienza. Il secondo l'ho preso io su un ambiente DDEV in container, il 25 settembre 2026.

Valore Dove Condizioni dichiarate
~4,7 ms/req laptop di sviluppo, database in Docker dodici sottomoduli attivi, tabelle vuote, 15 coppie da 6 richieste; da ~4,6 a ~5,7 su otto ripetizioni in due giorni
~7,0 ms/req DDEV in container su iMac Drupal 11.4.5, PHP 8.3, Xdebug spento, 15 coppie, tabelle non vuote
~1,8 ms/req stesso laptop di sviluppo senza i sottomoduli Execution e Spans; confronto appaiato a sé, 9 coppie da 6 richieste, contro un controllo di ~4,7 ms/req misurato nella stessa sessione con undici sottomoduli

La terza riga è quella che conta di più: spegnere due sottomoduli porta il costo da circa 4,7 a circa 1,8 millisecondi, cioè lo taglia del 62%. Le due cifre del taglio vengono dalla stessa sessione appaiata, non dal confronto fra la prima e la terza riga di questa tabella. Nessuno dei tre numeri è la risposta alla tua domanda, perché nessuna di quelle installazioni è la tua.

Perché due macchine danno due numeri diversi

Il costo di strumentare un'applicazione dipende dalla macchina che esegue l'istruzione in più, e le due macchine qui sopra differiscono su tutto ciò che conta: frequenza e generazione della CPU, stato dell'opcache, tipo di storage, carico concorrente al momento della misura, e lo strato di virtualizzazione che c'è o non c'è sotto.

Va detto anche quello che non ho tenuto costante: le due installazioni Drupal non avevano lo stesso contenuto. La documentazione dichiara che la misura piu' bassa è stata presa a tabelle vuote; la mia no. Il volume di dati sposta il lavoro di alcune strumentazioni, quindi lo scarto fra le due cifre va letto come differenza fra due ambienti nel loro insieme, non fra due processori. Dichiararlo costa una riga e rende il numero utilizzabile: una cifra senza le sue condizioni è lo stesso genere di dato che i fornitori di APM pubblicano senza dire dove l'hanno preso.

Perché il modulo ha smesso di dichiarare una percentuale

Prima della 2.0.0, e cioè fino alla 1.x compresa, native_observability pubblicava una stima che nessuno aveva mai misurato. Le note di rilascio della 2.0.0, che quel codice lo hanno rimosso, lo dicono senza giri di parole:

The report used to sum four hardcoded constants and print a made-up "Estimated overhead: 10%".

Quattro costanti scritte a mano nel sorgente, sommate, stampate come percentuale. Quel codice è stato rimosso nella 2.0.0. The Drop Times (si apre in una nuova scheda) ha dedicato un articolo a quella decisione e riporta la mia risposta scritta, in cui definivo quel 10% una sovrastima ricavata dalle mie prove, che non si poteva trasferire da un server all'altro. La frase è mia, non loro: è una citazione, non una conferma indipendente. La loro copertura si ferma al costo del modulo, che è una sola delle cose che il modulo fa: qui resto sullo stesso terreno, e cosa faccia per il resto sta nella scheda del progetto.

Al suo posto la 2.0.0 ha messo un comando. La scelta costa qualcosa a chi cerca una cifra sulla pagina del progetto e non la trova, e rende qualcosa a chi deve decidere se installare il modulo su un server preciso.

Sono io il maintainer del modulo, quindi questa sezione è il resoconto di una decisione mia. Le misure le puoi rifare con lo stesso comando. Il giudizio sulla decisione resta mio.

Le misure di questa pagina sono state prese sulla 2.0.1. La release stabile pubblicata sul progetto è 2.0.1, e se è più recente conviene rifare la misura prima di fidarsi dei numeri qui sotto.

Come si misura: il comando

Un comando, nessuna configurazione:

drush no:overhead:measure

Il comando confronta due stati della stessa installazione: cattura accesa e cattura spenta. Misurare entrambi gli stati sullo stesso sito isola il costo del modulo dalle differenze fra un server e un altro, che è esattamente ciò che rende inutile confrontare il tuo numero col mio.

Il modulo include due rotte di calibrazione, escluse da una misura ordinaria: una che non esegue nessuna query e nessun rendering, una che esegue un carico dichiarato e costante. Servono a far sì che la misura ponga la stessa domanda su qualunque installazione.

Come fa il comando a non mentire

Il protocollo è quello del benchmarking in ambiente rumoroso, applicato a una richiesta HTTP. Le note di rilascio della 2.0.0 lo descrivono per intero, e sono cinque accorgimenti:

  1. Blocchi appaiati. Ogni coppia esegue un blocco con la cattura accesa e uno con la cattura

spenta, così un rallentamento del server colpisce entrambi i lati.

  1. Alternanza. Il lato che parte per primo cambia da una coppia alla successiva, perché il primo

dei due paga l'ingresso a freddo.

  1. Prima coppia scartata. Serve a riscaldare cache e opcache e non entra nel calcolo.
  2. Mediana delle differenze appaiate. La mediana regge un valore anomalo, la media no.
  3. Test dei segni esatto bilaterale, con soglia p ≤ 0,05, più una passata separata con la

cattura spenta su entrambi i lati per misurare il rumore di fondo della macchina.

L'ultimo punto è quello che distingue una misura da un numero. Senza il rumore di fondo non sai se il delta che hai ottenuto è l'effetto del modulo o il respiro del tuo server.

Come leggo il risultato

Quattro valori decidono se il numero vale, e stanno tutti nell'output. Questo è il mio, tagliato alle righe che contano:

Fixed cost per request (a): 6.953 ms/req

calibration-minimal:
  - budget: 0.87% of the declared TTFB budget (good)
  - N 15 | IQR [6.908, 7.020] | noise 0.040 | signs 7/7 | p=0.01562
Valore Il mio Come si legge
N 15 coppie effettive dopo lo scarto del riscaldamento. Sotto 10 il test dei segni non arriva alla significatività
IQR [6.908, 7.020] metà centrale delle differenze. Se è larga quanto il valore, la misura non è stabile
noise 0,040 ms rumore di fondo della macchina. Il mio effetto ci sta sopra centosettantatré volte
p 0,01562 probabilità che i segni osservati vengano dal caso. Sopra 0,05 lo strumento marca il risultato unclear

Un delta che non superi il rumore viene dichiarato unclear invece di meas, e a quel punto la cosa utile da fare è rifare la misura su una macchina più tranquilla.

Circa 7 millisecondi sono tanti o pochi?

Dipende dal budget di risposta del tuo sito, e contro il mio sono circa lo 0,9%.

La soglia di riferimento arriva da Solving Big Data Challenges for Enterprise Application Performance Management (si apre in una nuova scheda) (Rabl, Gómez-Villamor, Sadoghi, Muntés-Mulero, Jacobsen, Mankovskii, VLDB 2012), che la formula così: «As a rule of thumb, a maximum tolerable overhead is five percent, but a smaller rate is preferable». Sopra quella soglia il monitoraggio degrada ciò che dovrebbe osservare.

Quanto la soglia venga rispettata è un'altra questione. groundcover osserva che il 3-5% ricorre nei benchmark che i fornitori di APM conducono su sé stessi, e cita una misura di Scout APM, che di New Relic è concorrente, in cui il suo agente aggiungeva oltre il 44% in uno scenario Ruby.

Budget TTFB del sito ~7,0 ms valgono Verdetto contro la soglia del 5%
800 ms ~0,9% largamente dentro
300 ms ~2,3% dentro
140 ms ~5% al limite

Gli 800 millisecondi non li ho scelti io: sono il valore di overhead.budget_ms nella configurazione del modulo, e il commento nel sorgente dice che vengono dalla soglia TTFB «good» documentata da web.dev. Serve a colorare il verdetto, e va sostituito col budget reale del tuo sito: una cifra in millisecondi senza il budget contro cui confrontarla non dice se il modulo sia sostenibile.

La scrittura sul database il visitatore non la paga

Le righe non vengono scritte durante la richiesta. DeferredPersistenceBuffer le accumula in memoria e le scarica con una sola INSERT multi-riga agganciata a KernelEvents::TERMINATE, l'evento che Drupal emette dopo che la risposta ha raggiunto il client. Il commento nel sorgente dice da dove si veniva: una richiesta carica spediva «circa 130 INSERT singole».

Tre dettagli del meccanismo, perché la differenza fra buffering e scrittura differita sta lì:

  • il buffer si svuota da sé oltre le 1000 righe, così una richiesta anomala non tiene in memoria un

volume illimitato;

  • flush() ingoia le eccezioni, perché un errore dell'osservabilità non deve far cadere la risposta

che stava osservando;

  • l'impostazione deferred_persistence_enabled riporta il modulo alla scrittura immediata, quando

serve per capire cosa stia succedendo al buffer.

Quello che invece il visitatore paga è la strumentazione, e resta dentro la richiesta. Nel censimento a livello di richiesta pubblicato nella documentazione del modulo (si apre in una nuova scheda) e ripreso da The Drop Times (si apre in una nuova scheda), su circa 6,3 millisecondi di lavoro del modulo circa 0,4 stavano nel flush differito (il 6,1%) mentre il restante 93,9% girava prima che la risposta partisse: tracciamento dell'esecuzione, collegamento degli span, osservazione della cache.

Quel censimento risponde a una domanda diversa dal costo fisso per richiesta, e i due numeri non vanno messi nella stessa colonna. Il censimento conta il lavoro che il modulo attribuisce a sé stesso. La misura appaiata conta la differenza fra un sito strumentato e lo stesso sito senza strumentazione, ed è quella che il visitatore paga.

Quanto raccoglie il modulo lo decidi tu, e i limiti sono già impostati

Ogni fonte di dati ha un tetto scritto nella configurazione predefinita, e nessuno di questi valori è cablato nel codice. Come impostarli sta nella pagina di configurazione della documentazione (si apre in una nuova scheda); questi sono i default, da config/install:

In native_observability.settings:

Impostazione Default Cosa limita
retention.max_rows 50.000 righe totali conservate
trace_retention_hours 72 vita delle tracce
spans_retention_hours 24 vita degli span di esecuzione
metrics_retention_days 7 vita delle metriche aggregate
cleanup_batch_limit 5.000 righe cancellate per giro di pulizia

I due observer sono sottomoduli e hanno un oggetto di configurazione proprio. In native_observability_database_observer.settings:

Impostazione Default Cosa limita
slow_query_threshold_ms 100 sopra quanti millisecondi una query viene registrata
max_stored_queries_per_request 20 query conservate per richiesta
retention_hours 72 vita delle query registrate

In native_observability_cache_observer.settings:

Impostazione Default Cosa limita
max_stored_invalidations_per_request 50 invalidazioni di cache conservate per richiesta
retention_hours 72 vita degli eventi di cache registrati

Le due soglie per richiesta sono quelle che tengono il costo costante quando una pagina si comporta male: una rotta che esegue trecento query ne fa registrare venti, non trecento.

Sul lato dei dati personali i default partono chiusi, e questo abbassa anche il lavoro: il corpo della richiesta, la query string e gli header non vengono raccolti (body_mode, query_mode, headers_mode sono a off), l'indirizzo IP è anonimizzato e dello user agent resta solo la famiglia. Il modulo esclude inoltre le proprie rotte dalla cattura (exclude_own_routes), così aprire la dashboard non gonfia i contatori che stai leggendo.

Cosa dichiarano gli altri strumenti

Nessuno dei fornitori di APM per PHP pubblica una cifra ottenuta sulla macchina del cliente, e due dei quattro che ho consultato non pubblicano alcuna cifra. La colonna che conta non è quanto dichiarano, è a quali condizioni.

Strumento Cosa pubblica A quali condizioni
Tideways 4,93% su PHP 5.6 e 17,11% su PHP 7 per Timeline al 10% di campionamento, 13,41% e 23,86% per XHProf benchmark oss-performance contro WordPress, con la macchina spinta al limite e tutti i core saturi. Il fornitore avverte che «for actual applications the overhead is smaller» e che il risultato «is just representive of WordPress»
Blackfire «close-to-no overhead» sulle trace standard, e fino al 15% misurato sulle Extended Traces massimo rilevato dal fornitore, con Drupal nominato esplicitamente insieme a Symfony, Prestashop 1.7+ e Ibexa DXP
New Relic nessuna cifra nella documentazione consultata (si apre in una nuova scheda), che spiega come ridurre l'overhead non applicabile
Datadog nessuna cifra nella documentazione consultata (si apre in una nuova scheda), che copre i limiti di frequenza dell'agente non applicabile

Le percentuali di Tideways non si confrontano con la mia. Misurano WordPress su PHP 5.6 e PHP 7, sotto un carico costruito per saturare la macchina, mentre il mio numero viene da Drupal 11.4.5 su PHP 8.3. Altro CMS, due versioni maggiori di PHP di distanza, condizioni opposte.

Quello che si confronta è il comportamento. Tideways e Blackfire pubblicano numeri misurati e ne dichiarano i limiti, e quella è la cosa giusta da fare anche quando il numero che esce non è lusinghiero. New Relic e Datadog, sulle pagine che ho letto, non pubblicano niente. Il confronto che regge è questo, e non ha percentuali dentro.

Che cosa chiedere a chi pubblica un numero di prestazioni

Quattro domande, e valgono per qualunque strumento, non solo per questo. Non sono teoriche: le ho scritte dopo aver trovato tre difetti che falsavano la misura del mio stesso modulo, elencati con i loro numeri nelle note di rilascio della 2.0.0 (si apre in una nuova scheda).

  1. Lo strumento si esclude dalla propria misura? Chi traccia anche le rotte con cui si misura

conta sé stesso, e il segno dell'errore non è prevedibile: nel mio caso il costo risultava più basso del 55%, non più alto.

  1. La ripetizione è protetta dalla cache? Se la seconda esecuzione può essere servita dalla

cache della prima, il numero pubblicato è il tempo della cache: circa due ordini di grandezza più basso, cioè un costo che non esiste.

  1. La configurazione viene riletta? Un servizio che legge le impostazioni una volta sola, per

la vita della propria istanza, funziona sotto PHP-FPM e mente in un runtime persistente. È la classe di problema del meta issue del core sui server applicativi persistenti (si apre in una nuova scheda), che elenca ReactPHP, PHP-PM, PHPFastCGI, FrankenPHP e Swoole.

  1. Il rumore di fondo è dichiarato? Senza, non si distingue l'effetto misurato dal respiro della

macchina, ed è il motivo per cui noise sta dentro il risultato del comando insieme al valore.

Se chi pubblica un numero non risponde a queste quattro, quel numero vale quanto valeva il «10%» stampato dalla 1.x.

Cosa faccio con questo numero

Misuro prima di installare in produzione, e rimisuro dopo ogni cambio di macchina o di versione di PHP. La procedura sta in quattro passi:

  1. Installare il modulo su un ambiente identico a quello di produzione per versione di PHP, di

Drupal e di database, con Xdebug spento: Xdebug strumenta ogni chiamata di funzione e qualunque misura fatta con lui acceso va buttata.

  1. Eseguire drush no:overhead:measure senza altro carico sulla macchina.
  2. Leggere N, IQR, noise e p prima del valore. Se il verdetto è unclear, il valore non si

usa.

  1. Dividere il costo per il budget di risposta del sito e confrontare con la soglia che ti sei dato.

I passaggi di installazione stanno nella documentazione del modulo (si apre in una nuova scheda), e cosa il modulo faccia davvero nella scheda del progetto su questo sito. Il numero che ottieni vale per la tua macchina e per quella installazione. Il mio l'ho pubblicato perché serva da termine di paragone sull'ordine di grandezza, e perché si veda che due misure dello stesso codice possono stare a mezzo millisecondo o a due millisecondi di distanza.

Fonti e riferimenti

Tutte le fonti sono state consultate il 27 settembre 2026.

  1. Native Observability, pagina del progetto (si apre in una nuova scheda). Requisiti, comando di misura, release stabile 2.0.1.
  2. Native Observability, documentazione: il costo del modulo (si apre in una nuova scheda). Le cifre 4,684, 1,795, 6,253 e 0,379 con le loro condizioni e la tabella di provenienza.
  3. Native Observability, documentazione: configurazione (si apre in una nuova scheda) e installazione (si apre in una nuova scheda).
  4. Native Observability 2.0.0, note di rilascio (si apre in una nuova scheda). Rimozione della stima a costanti, protocollo di misura appaiata, test dei segni.
  5. Native Observability 2.0.0 Measures Its Own Performance Cost, The Drop Times (si apre in una nuova scheda). Censimento a livello di richiesta, 6,253 ms e scomposizione del flush differito.
  6. APM Overheads: Is Your APM Slowing You Down?, groundcover (si apre in una nuova scheda). Il 3-5% nei benchmark dei fornitori, e la misura indipendente oltre il 44% su uno scenario Ruby.
  7. Profiling Overhead and PHP 7, Tideways (si apre in una nuova scheda). Overhead misurato dal fornitore su PHP 5.6 e PHP 7, da 4,93% a 23,86%.
  8. Configuring Blackfire Monitoring (si apre in una nuova scheda). «close-to-no overhead» sulle trace standard, fino al 15% misurato sulle Extended Traces.
  9. PHP agent overhead reduction tips, New Relic (si apre in una nuova scheda). Assenza di una cifra dichiarata.
  10. Agent Rate Limits, Datadog (si apre in una nuova scheda). Assenza di una cifra dichiarata; la pagina copre i limiti di frequenza dell'agente.
  11. Robust benchmarking in noisy environments (si apre in una nuova scheda). Rumore del sistema operativo, riscaldamento, filtro degli anomali.
  12. Make Drupal compatible with persistent app servers like ReactPHP, PHP-PM, PHPFastCGI, FrankenPHP, Swoole, core #2218651 (si apre in una nuova scheda). La classe di difetto della configurazione letta una volta per istanza.
  13. Solving Big Data Challenges for Enterprise Application Performance Management, Rabl et al., VLDB 2012 (si apre in una nuova scheda). La soglia del 5% come regola pratica.
Giorgio Alfredo Pagano
Modificato dall'AI

Questo contenuto è stato prodotto dall'AI e rivisto da una persona.

Come è stata usata l'AI?

Le bozze sono prodotte con l'assistenza dell'AI, poi dirette, rivedute e verificate da una persona. Numeri, date e versioni sono confrontati con le fonti pubbliche prima della pubblicazione, e la data di quel controllo è indicata nel testo.