Medición del rendimiento con la temporización del servidor

Publicado: 2022-03-10
Resumen rápido ↬ El encabezado Tiempo del servidor proporciona una forma discreta y conveniente de comunicar los tiempos de rendimiento del servidor back-end a las herramientas de desarrollo en el navegador. Agregar información de tiempo a su aplicación le permite monitorear el rendimiento de back-end y front-end en un solo lugar.

Al emprender cualquier tipo de trabajo de optimización del rendimiento, una de las primeras cosas que aprendemos es que antes de poder mejorar el rendimiento, primero debe medirlo. Sin poder medir la velocidad a la que funciona algo, no podemos saber si los cambios que se realizan mejoran el rendimiento, no tienen efecto o incluso empeoran las cosas.

Muchos de nosotros estaremos familiarizados con el trabajo en un problema de rendimiento en algún nivel. Eso podría ser algo tan simple como tratar de descubrir por qué JavaScript en su página no se activa lo suficientemente pronto, o por qué las imágenes tardan demasiado en aparecer en el mal wifi del hotel. La respuesta a este tipo de preguntas a menudo se encuentra en un lugar muy familiar: las herramientas de desarrollo de su navegador.

A lo largo de los años, las herramientas para desarrolladores se han mejorado para ayudarnos a solucionar este tipo de problemas de rendimiento en la interfaz de usuario de nuestras aplicaciones. Los navegadores ahora incluso tienen auditorías de rendimiento integradas. Esto puede ayudar a rastrear problemas de front-end, pero estas auditorías pueden mostrar otra fuente de lentitud que no podemos solucionar en el navegador. Ese problema son los tiempos de respuesta lentos del servidor.

“Tiempo hasta el primer byte”

Las optimizaciones del navegador pueden hacer muy poco para mejorar una página que simplemente es lenta de construir en el servidor. Ese costo se incurre entre que el navegador hace la solicitud del archivo y recibe la respuesta. Estudiar el gráfico de cascada de su red en las herramientas de desarrollo mostrará este retraso en la categoría de "Esperando (TTFB)". Este es el tiempo que el navegador espera entre realizar la solicitud y recibir la respuesta.

¡Más después del salto! Continúe leyendo a continuación ↓

En términos de rendimiento, esto se conoce como Tiempo hasta el primer byte : la cantidad de tiempo que transcurre antes de que el servidor comience a enviar algo con lo que el navegador pueda comenzar a trabajar. Incluido en ese tiempo de espera está todo lo que el servidor necesita hacer para construir la página. Para un sitio típico, eso podría implicar el enrutamiento de la solicitud a la parte correcta de la aplicación, la autenticación de la solicitud, la realización de múltiples llamadas a sistemas back-end como bases de datos, etc. Podría implicar ejecutar contenido a través de sistemas de plantillas, hacer llamadas de API a servicios de terceros y tal vez incluso cosas como enviar correos electrónicos o cambiar el tamaño de las imágenes. Cualquier trabajo que haga el servidor para completar una solicitud se reduce a esa espera TTFB que el usuario experimenta en su navegador.

El panel Red en Chrome DevTools que muestra la inspección de una solicitud de una sola página
La inspección de una solicitud de documento muestra el tiempo que el navegador pasa esperando la respuesta del servidor.

Entonces, ¿cómo reducimos ese tiempo y comenzamos a entregar la página más rápidamente al usuario? Bueno, esa es una gran pregunta, y la respuesta depende de su aplicación. Ese es el trabajo de la optimización del rendimiento en sí. Lo que debemos hacer primero es medir el rendimiento para poder juzgar el beneficio de cualquier cambio.

El encabezado de temporización del servidor

El trabajo de Server Timing no es ayudarlo a cronometrar la actividad en su servidor. Tendrá que hacer el cronometraje usted mismo utilizando cualquier conjunto de herramientas que su plataforma de back-end tenga disponible para usted. Más bien, el propósito de Server Timing es especificar cómo se pueden comunicar esas medidas al navegador.

La forma en que se hace esto es muy simple, transparente para el usuario y tiene un impacto mínimo en el peso de su página. La información se envía como un conjunto simple de encabezados de respuesta HTTP.

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

Este ejemplo comunica dos puntos de tiempo diferentes llamados db y tmpl . Estos no son parte de la especificación: estos son nombres que hemos elegido, en este caso para representar algunos tiempos de base de datos y plantillas, respectivamente.

La propiedad dur indica el número de milisegundos que tardó en completarse la operación. Si observamos la solicitud en la sección Red de Herramientas para desarrolladores, podemos ver que los tiempos se agregaron al gráfico.

El panel Tiempos de una solicitud de página en Chrome DevTools que muestra una nueva sección Tiempos del servidor.
Aparece una nueva sección Tiempo del servidor, que muestra los tiempos establecidos con el encabezado HTTP Server-Timing.

El encabezado Server-Timing puede tomar varias métricas separadas por comas:

 Server-Timing: metric, metric, metric

Cada métrica puede especificar tres propiedades posibles

  1. Un nombre corto para la métrica (como db en nuestro ejemplo)
  2. Una duración en milisegundos (expresada como dur=123 )
  3. Una descripción (expresada como desc="My Description" )

Cada propiedad se separa con un punto y coma como delimitador. Podríamos agregar descripciones a nuestro ejemplo así:

 Server-Timing: db;dur=123;desc="Database", tmpl;dur=56;desc="Template processing"
El panel Tiempos de una solicitud de página en Chrome DevTools que muestra las descripciones utilizadas para las métricas de tiempo del servidor.
Los nombres se reemplazan con descripciones cuando se proporcionan.

La única propiedad que se requiere es el name . Tanto dur como desc son opcionales y se pueden usar opcionalmente cuando sea necesario. Por ejemplo, si necesita depurar un problema de temporización que estaba ocurriendo en un servidor o centro de datos y no en otro, podría ser útil agregar esa información a la respuesta sin una temporización asociada.

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

Esto aparecería junto con los tiempos.

El panel de tiempos de una solicitud de página en Chrome DevTools que muestra un tiempo de servidor sin tiempo establecido.
Se muestra el valor "Centro de datos de la costa este", aunque no tiene tiempos.

Una cosa que puede notar es que las barras de tiempo no aparecen en un patrón de cascada. Esto se debe simplemente a que Server Timing no intenta comunicar la secuencia de tiempos, solo las métricas sin procesar.

Implementación de la temporización del servidor

La implementación exacta dentro de su propia aplicación dependerá de su circunstancia específica, pero los principios son los mismos. Los pasos siempre van a ser:

  1. Tiempo algunas operaciones
  2. Recoger juntos los resultados de tiempo
  3. Salida del encabezado HTTP

En pseudocódigo, la generación de respuesta podría verse así:

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

Los conceptos básicos para implementar algo en ese sentido deberían ser sencillos en cualquier idioma. Una implementación de PHP muy simple podría usar la función microtime() para las operaciones de temporización, y podría parecerse a lo siguiente.

 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, ', '); } }

Un script de prueba lo usaría como se muestra a continuación, aquí usando la función usleep() para crear artificialmente un retraso en la ejecución del script para simular un proceso que lleva tiempo completar.

 $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());

Ejecutar este código generó un encabezado que se veía así:

 Server-Timing: db;dur=201.098919, tpl;dur=301.271915;desc="Templating", geo;dur=404.520988;desc="Geocoding"
El panel Tiempos de una solicitud de página en Chrome DevTools que muestra los valores de prueba mostrados correctamente.
Los tiempos del servidor establecidos en el ejemplo aparecen en el panel Tiempos con los retrasos configurados en nuestro script de prueba.

Implementaciones existentes

Teniendo en cuenta lo útil que es Server Timing, hay relativamente pocas implementaciones que pude encontrar. El paquete NPM de temporización del servidor ofrece una manera conveniente de usar la temporización del servidor desde proyectos de nodos.

Si utiliza un marco PHP basado en middleware, tuupola/server-timing-middleware también ofrece una opción útil. Lo he estado usando en producción en Notist durante algunos meses, y siempre dejo habilitados algunos tiempos básicos si desea ver un ejemplo en la naturaleza.

Para la compatibilidad con navegadores, lo mejor que he visto está en Chrome DevTools, y eso es lo que he usado para las capturas de pantalla de este artículo.

Consideraciones

Server Timing en sí agrega una sobrecarga mínima a la respuesta HTTP enviada de vuelta por cable. El encabezado es muy mínimo y, en general, es seguro enviarlo sin preocuparse por la orientación solo a usuarios internos. Aun así, vale la pena mantener los nombres y las descripciones breves para no agregar gastos generales innecesarios.

Más preocupante es el trabajo adicional que podría estar haciendo en el servidor para cronometrar su página o aplicación. Agregar tiempo y registro adicionales puede tener un impacto en el rendimiento, por lo que vale la pena implementar una forma de activarlo y desactivarlo cuando sea necesario.

El uso de un encabezado de sincronización del servidor es una excelente manera de asegurarse de que se pueda acceder a toda la información de sincronización desde el front-end y el back-end de su aplicación en una ubicación. Siempre que su aplicación no sea demasiado compleja, puede ser fácil de implementar y puede estar en funcionamiento en muy poco tiempo.

Si desea obtener más información sobre la temporización del servidor, puede intentar lo siguiente:

  • La especificación de tiempo del servidor W3C
  • La página de MDN en Server Timing tiene ejemplos y detalles actualizados del soporte del navegador
  • Un artículo interesante del equipo de BBC iPlayer sobre el uso de Server Timing.