Misurare le prestazioni con il tempo del server

Pubblicato: 2022-03-10
Riepilogo rapido ↬ L'intestazione Server Timing fornisce un modo discreto e conveniente per comunicare i tempi delle prestazioni del server back-end agli strumenti di sviluppo nel browser. L'aggiunta di informazioni sui tempi all'applicazione consente di monitorare le prestazioni di back-end e front-end in un unico posto.

Quando si intraprende qualsiasi tipo di lavoro di ottimizzazione delle prestazioni, una delle prime cose che impariamo è che prima di poter migliorare le prestazioni è necessario prima misurarle. Senza essere in grado di misurare la velocità con cui qualcosa funziona, non possiamo dire se le modifiche apportate migliorano le prestazioni, non hanno alcun effetto o addirittura peggiorano le cose.

Molti di noi avranno familiarità con il lavoro su un problema di prestazioni a un certo livello. Potrebbe essere qualcosa di semplice come cercare di capire perché JavaScript sulla tua pagina non si attiva abbastanza presto o perché le immagini impiegano troppo tempo per essere visualizzate su un cattivo wifi dell'hotel. La risposta a questo tipo di domande si trova spesso in un luogo molto familiare: gli strumenti di sviluppo del tuo browser.

Nel corso degli anni gli strumenti per sviluppatori sono stati migliorati per aiutarci a risolvere questo tipo di problemi di prestazioni nel front-end delle nostre applicazioni. I browser ora hanno anche controlli delle prestazioni integrati. Questo può aiutare a rintracciare i problemi del front-end, ma questi controlli possono mostrare un'altra fonte di lentezza che non possiamo correggere nel browser. Questo problema sono i tempi di risposta del server lenti.

"Tempo al primo byte"

C'è molto poco che le ottimizzazioni del browser possono fare per migliorare una pagina che è semplicemente lenta da costruire sul server. Tale costo viene sostenuto tra il browser che effettua la richiesta del file e la ricezione della risposta. Lo studio del grafico a cascata della rete negli strumenti di sviluppo mostrerà questo ritardo nella categoria "In attesa (TTFB)". Questo è il tempo che il browser attende tra la richiesta e la ricezione della risposta.

Altro dopo il salto! Continua a leggere sotto ↓

In termini di prestazioni, questo è noto come Time to First Byte - la quantità di tempo necessaria prima che il server inizi a inviare qualcosa con cui il browser può iniziare a lavorare. Racchiuso in quel tempo di attesa c'è tutto ciò che il server deve fare per costruire la pagina. Per un sito tipico, ciò potrebbe comportare l'instradamento della richiesta alla parte corretta dell'applicazione, l'autenticazione della richiesta, l'esecuzione di più chiamate a sistemi di back-end come database e così via. Potrebbe comportare l'esecuzione di contenuti attraverso sistemi di modelli, l'esecuzione di chiamate API a servizi di terze parti e forse anche cose come l'invio di e-mail o il ridimensionamento delle immagini. Qualsiasi lavoro svolto dal server per completare una richiesta viene compresso in quell'attesa TTFB che l'utente sperimenta nel proprio browser.

Il pannello Rete in Chrome DevTools che mostra l'ispezione di una singola richiesta di pagina
L'ispezione di una richiesta di documento mostra il tempo che il browser trascorre in attesa della risposta dal server.

Quindi, come possiamo ridurre questo tempo e iniziare a fornire la pagina più rapidamente all'utente? Bene, questa è una grande domanda e la risposta dipende dalla tua applicazione. Questo è il lavoro stesso dell'ottimizzazione delle prestazioni. Quello che dobbiamo fare prima è misurare le prestazioni in modo da poter giudicare il beneficio di eventuali modifiche.

L'intestazione del tempo del server

Il compito di Server Timing non è aiutarti a cronometrare effettivamente l'attività sul tuo server. Dovrai fare il cronometraggio da solo utilizzando qualsiasi set di strumenti che la tua piattaforma di back-end ti mette a disposizione. Piuttosto, lo scopo di Server Timing è specificare come queste misurazioni possono essere comunicate al browser.

Il modo in cui ciò avviene è molto semplice, trasparente per l'utente e ha un impatto minimo sul peso della tua pagina. Le informazioni vengono inviate come un semplice insieme di intestazioni di risposta HTTP.

 Server-Timing: db;dur=123, tmpl;dur=56

Questo esempio comunica due diversi punti di temporizzazione denominati db e tmpl . Questi non fanno parte delle specifiche: sono nomi che abbiamo scelto, in questo caso per rappresentare rispettivamente alcuni tempi di database e template.

La proprietà dur indica il numero di millisecondi necessari per il completamento dell'operazione. Se osserviamo la richiesta nella sezione Rete degli Strumenti per sviluppatori, possiamo vedere che le tempistiche sono state aggiunte al grafico.

Il pannello Tempi di una richiesta di pagina in Chrome DevTools che mostra una nuova sezione Tempi del server.
Viene visualizzata una nuova sezione Server Timing, che mostra i tempi impostati con l'intestazione HTTP Server-Timeing.

L'intestazione Server-Timing può richiedere più metriche separate da virgole:

 Server-Timing: metric, metric, metric

Ogni metrica può specificare tre possibili proprietà

  1. Un nome breve per la metrica (come db nel nostro esempio)
  2. Una durata in millisecondi (espressa come dur=123 )
  3. Una descrizione (espressa come desc="My Description" )

Ogni proprietà è separata da un punto e virgola come delimitatore. Potremmo aggiungere descrizioni al nostro esempio in questo modo:

 Server-Timing: db;dur=123;desc="Database", tmpl;dur=56;desc="Template processing"
Il pannello Tempi di una richiesta di pagina in Chrome DevTools che mostra le descrizioni utilizzate per le metriche di tempi del server.
I nomi vengono sostituiti con descrizioni quando forniti.

L'unica proprietà richiesta è name . Sia dur che desc sono opzionali e possono essere utilizzati opzionalmente dove richiesto. Ad esempio, se era necessario eseguire il debug di un problema di temporizzazione che si stava verificando su un server o data center e non su un altro, potrebbe essere utile aggiungere tali informazioni nella risposta senza un tempo associato.

 Server-Timing: datacenter;desc="East coast data center", db;dur=123;desc="Database", tmpl;dur=56;desc="Template processing”

Questo verrebbe quindi visualizzato insieme ai tempi.

Il pannello Tempi di una richiesta di pagina in Chrome DevTools che mostra un tempo del server senza tempo impostato.
Viene visualizzato il valore "Centro dati costa orientale", anche se non ha temporizzazioni.

Una cosa che potresti notare è che le barre di temporizzazione non vengono visualizzate in uno schema a cascata. Questo semplicemente perché Server Timing non tenta di comunicare la sequenza di tempi, ma solo le metriche grezze stesse.

Implementazione della tempistica del server

L'esatta implementazione all'interno della tua applicazione dipenderà dalla tua circostanza specifica, ma i principi sono gli stessi. I passaggi saranno sempre:

  1. Tempo alcune operazioni
  2. Raccogli insieme i risultati dei tempi
  3. Emetti l'intestazione HTTP

In pseudocodice, la generazione della risposta potrebbe essere simile a questa:

 startTimer('db') getInfoFromDatabase() stopTimer('db') startTimer('geo') geolocatePostalAddressWithAPI('10 Downing Street, London, UK') endTimer('geo') outputHeader('Server-Timing', getTimerOutput())

Le basi per implementare qualcosa in questo senso dovrebbero essere semplici in qualsiasi lingua. Un'implementazione PHP molto semplice potrebbe utilizzare la funzione microtime() per le operazioni di temporizzazione e potrebbe avere un aspetto simile a quanto segue.

 class Timers { private $timers = []; public function startTimer($name, $description = null) { $this->timers[$name] = [ 'start' => microtime(true), 'desc' => $description, ]; } public function endTimer($name) { $this->timers[$name]['end'] = microtime(true); } public function getTimers() { $metrics = []; if (count($this->timers)) { foreach($this->timers as $name => $timer) { $timeTaken = ($timer['end'] - $timer['start']) * 1000; $output = sprintf('%s;dur=%f', $name, $timeTaken); if ($timer['desc'] != null) { $output .= sprintf(';desc="%s"', addslashes($timer['desc'])); } $metrics[] = $output; } } return implode($metrics, ', '); } }

Uno script di test lo userebbe come di seguito, qui usando la funzione usleep() per creare artificialmente un ritardo nell'esecuzione dello script per simulare un processo che richiede tempo per essere completato.

 $Timers = new Timers(); $Timers->startTimer('db'); usleep('200000'); $Timers->endTimer('db'); $Timers->startTimer('tpl', 'Templating'); usleep('300000'); $Timers->endTimer('tpl'); $Timers->startTimer('geo', 'Geocoding'); usleep('400000'); $Timers->endTimer('geo'); header('Server-Timing: '.$Timers->getTimers());

L'esecuzione di questo codice ha generato un'intestazione simile a questa:

 Server-Timing: db;dur=201.098919, tpl;dur=301.271915;desc="Templating", geo;dur=404.520988;desc="Geocoding"
Il pannello Tempi di una richiesta di pagina in Chrome DevTools che mostra i valori di test visualizzati correttamente.
I tempi del server impostati nell'esempio vengono visualizzati nel pannello Tempi con i ritardi configurati nel nostro script di test.

Implementazioni esistenti

Considerando quanto sia utile Server Timing, ci sono relativamente poche implementazioni che potrei trovare. Il pacchetto NPM di temporizzazione del server offre un modo conveniente per utilizzare il tempo del server dai progetti Node.

Se si utilizza un framework PHP basato su middleware, tuupola/server-timing-middleware fornisce anche un'opzione pratica. Lo uso in produzione su Notist da alcuni mesi e lascio sempre abilitati alcuni tempi di base se desideri vedere un esempio in natura.

Per il supporto del browser, il meglio che ho visto è in Chrome DevTools, ed è quello che ho usato per gli screenshot in questo articolo.

Considerazioni

Server Timing stesso aggiunge un sovraccarico minimo alla risposta HTTP restituita via cavo. L'intestazione è molto minima ed è generalmente sicura da inviare senza preoccuparsi del targeting solo per utenti interni. Anche così, vale la pena mantenere nomi e descrizioni brevi in ​​modo da non aggiungere spese inutili.

Più preoccupante è il lavoro extra che potresti svolgere sul server per sincronizzare la tua pagina o applicazione. L'aggiunta di tempi e registrazione aggiuntivi può di per sé avere un impatto sulle prestazioni, quindi vale la pena implementare un modo per attivarli e disattivarli quando necessario.

L'utilizzo di un'intestazione Server Timing è un ottimo modo per assicurarsi che tutte le informazioni sui tempi sia dal front-end che dal back-end dell'applicazione siano accessibili in un'unica posizione. A condizione che la tua applicazione non sia troppo complessa, può essere facile da implementare e puoi essere operativa in un lasso di tempo molto breve.

Se desideri saperne di più su Server Timing, potresti provare quanto segue:

  • La specifica di temporizzazione del server W3C
  • La pagina MDN su Server Timing contiene esempi e dettagli aggiornati sul supporto del browser
  • Un interessante resoconto del team di BBC iPlayer sull'uso di Server Timing.