HTML 5 User Timing

Hace unos años atrás, nadie se cuestionaba el hecho de medir tiempos en el código implementado en JavaScript. Su uso era tan básico y tan mínimo que no suponía una penalización en el rendimiento de la aplicación. A día de hoy un desarrollo en el lado del cliente mal enfocado puede resultar desastroso para la experiencia del usuario.
Por suerte, en la especificación de HTML 5 se está teniendo muy en cuenta el ofrecer a los desarrolladores los mecanismos suficientes para poder medir diferentes aspectos de las web apps. Unos post atrás estuve hablando de Navigation Timing, la cual nos proporciona información relacionada con la navegación desde distintos puntos. Hoy me gustaría centrarme en HTML 5 User Timing API con la que podemos medir diferentes puntos de nuestra aplicación con una precisión realmente alta, gracias al uso de timestamps.

PerformanceMark y PerformanceMeasure

Para trabajar con esta API debemos hacer uso de dos interfaces, ambas extensiones de la interfaz perfomance:

PerformanceMark
Utilizamos performance.mark para almacenar el timestamp asociado a un nombre pasado como parámetro. Estas marcas las usaremos para combinarlas entre ellas y tomar las medidas.
PerformanceMeasure
Con la ayuda de performance.measure generaremos los resultados basándonos en las marcas tomadas anteriormente, obteniendo el cálculo entre una y otra de manera automática.

Un ejemplo claro de cómo trabajaríamos con estas interfaces sería el siguiente:

window.onload = function () {

    function sleep(milliseconds) {
        var start = new Date().getTime();
        for (; ; ) {
            if ((new Date().getTime() - start) > milliseconds) {
                break;
            }
        }
    }

    function Task1() {
        sleep(2000);
    }

    function Task2() {
        sleep(3000);
    }

    performance.mark("start task 1");

    Task1();

    performance.mark("end task 1");

    performance.mark("start task 2");

    Task2();

    performance.mark("end task 2");

    performance.measure("Task 1 duration", "start task 1", "end task 1");
    performance.measure("Task 2 duration", "start task 2", "end task 2");

    getMeasures();

    function getMeasures() {

        //var performanceEntries = performance.getEntriesByType("mark");
        var performanceEntries = performance.getEntriesByType("measure");

        for (var i = 0; i < performanceEntries.length; i++) {

            console.log(performanceEntries[i]);
        }
    }

}

Como podemos ver en el código anterior, se han creado dos funciones, Task1 y Task2, donde realizamos llamadas a una tercera llamada sleep, con el objetivo de generar un cierto retraso en su ejecución. Antes y después de cada llamada añadidos diferentes marcas para finalmente realizar el cálculo a través de performance.measure, donde pasamos como parámetro una descripción y el nombre de las marcas que tomamos como referencia.
Si nos fijamos en la consola tenemos los siguientes resultados:

PerformanceMeasure console

Los valores que nos devuelve son:

  • duration: Se trata del cálculo entre las dos marcas. En el caso de los elementos de tipo mark este valor siempre es cero.
  • startTime: Timestamp de inicio.
  • entryType: Propiedad que nos devuelve el tipo: measure o mark.
  • name: Nombre descriptivo que dimos a la medida.

Por otro lado, disponemos de otros métodos a través de la interfaz performance:

  • clearMarks([marks]): Elimina una o todas las marks almacenadas.
  • clearMeasures([measure]): Exactamente igual que el método anterior pero en este caso para las measures.
  • getEntriesByType(type) y getEntriesByName(name): La primera de ellas se utilizó en el ejemplo, para recuperar todas las entradas de tipo medida, pero también podemos obtener los elementos a través del nombre asignado.

A día de hoy User Timing está soportada por los navegadores principales, a excepción de Firefox.
Espero que sea de utilidad 🙂

¡Saludos!