Cómo medir el rendimiento de los gráficos del navegador

Ilmari Heikkinen

En pocas palabras, las comparativas de gráficos del navegador consisten en dibujar tanto como sea posible y, al mismo tiempo, mantener una velocidad de fotogramas fluida. Una vez que disminuya la velocidad de fotogramas, sabrás cuánto puedes dibujar por fotograma. Fin de la publicación. ¿No? De acuerdo, te explicaré más.

¡Hora del ejemplo! Este es un pequeño fragmento de código con una función de comparativa tick. La función tick llama a una función draw con una carga de dibujo creciente hasta que el dibujo tarda más de 33 ms de forma constante.

var t, previousTime;
var drawLoad = 1;
var slowCount = 0;
var maxSlow = 10;
// Note, you might need to polyfill performance.now and requestAnimationFrame
t = previousTime = performance.now();
var tick = function() {
    var maximumFrameTime = 1000/30; // 30 FPS
    t = performance.now();
    var elapsed = t - previousTime;
    previousTime = t;
    if (elapsed < maximumFrameTime || slowCount < maxSlow) {
        if (elapsed < maximumFrameTime) {
            drawLoad+=10;
        } else {
            slowCount++;
        }
        draw(drawLoad);
        requestAnimationFrame(tick);
    } else {
        // found maximum sustainable load at 30 FPS
        document.getElementById('res').innerHTML = ("could draw "+(drawLoad)+" in " +
            maximumFrameTime + " ms");
    }
};
requestAnimationFrame(tick);

​ Consulta el ejemplo en vivo en jsFiddle.

Puedes ver cómo la comparativa sigue dibujando más y más hasta que llega al punto en que se ralentiza. Esta es una forma sencilla y agradable de averiguar cuánto puedes dibujar con una velocidad de fotogramas fluida. También puedes conectar tu propia función de dibujo al ejemplo y realizar algunas comparativas personalizadas. ¡Genial!

Consideraciones y errores comunes cuando se comparan las gráficas del navegador

Entonces, si el ejemplo anterior es la forma correcta de hacerlo, ¿cuáles son las formas no tan correctas? Las formas en que se realizan comparativas de elementos no relacionados o que proporcionan métricas de rendimiento extrañas que no parecen tener nada que ver con la velocidad a la que se ejecuta tu app. Me alegra que lo preguntes. Estos son los dos más comunes que he visto en la Web.

Medición de FPS máximos: Dibuja un poco en cada fotograma y mide los FPS. No funciona bien para medir el rendimiento de los gráficos en Chrome porque la implementación de gráficos subyacente está sincronizada con la frecuencia de actualización de la pantalla (por lo que obtienes un máximo de 60 actualizaciones de pantalla por segundo). Medir la velocidad de las llamadas de dibujo tampoco será muy útil, ya que el sistema de dibujo de Chrome coloca tus comandos de dibujo en un búfer de comandos que se ejecuta en la próxima actualización de la pantalla.

Usar setTimeout para medir el rendimiento de los gráficos es otra mala idea. El intervalo de setTimeout se limita a 4 ms en los navegadores, por lo que lo máximo que puedes obtener es 250 FPS. Históricamente, los navegadores tenían diferentes intervalos mínimos, por lo que es posible que hayas tenido una comparativa de dibujo trivial muy dañada que mostrara que el navegador A se ejecutaba a 250 FPS (intervalo mínimo de 4 ms) y el navegador B a 100 FPS (intervalo mínimo de 10 ms). Claramente, A es más rápido. No. Es posible que B ejecute el código de dibujo más rápido que A, por ejemplo, A tardó 3 ms y B tardó 1 ms. No afecta los FPS, ya que el tiempo de dibujo es inferior al intervalo mínimo de setTimeout. Y si el navegador se renderiza de forma asíncrona, no hay nada que hacer. No uses setTimeout, a menos que sepas lo que estás haciendo.

Cómo hacerlo

Una mejor manera de obtener comparativas es usar una carga de dibujo realista y multiplicarla hasta que la velocidad de fotogramas comience a disminuir. Por ejemplo, si escribes un juego de arriba abajo con un terreno de mapa de mosaicos, intenta dibujar el mapa de mosaicos en cada fotograma y comprueba si se ejecuta a 60 FPS. Si es así, aumenta la carga (dibuja el mapa de mosaicos dos veces por fotograma, con una limpieza en el medio). Continúa aumentando hasta que los FPS disminuyan a un nuevo nivel estable. Ahora sabes cuántas capas de mapa de mosaicos puedes dibujar por fotograma.

Las diferentes aplicaciones gráficas tienen necesidades diferentes, por lo que debes escribir tus comparativas teniendo en cuenta esto. Mide las funciones gráficas que usas en tu app. Cuando encuentres una situación de lentitud, intenta reducirla al fragmento de código más pequeño que la reproduzca (y envía un informe de errores a new.crbug.com si debería ser más rápido).

Para ver cómo escribir código de gráficos web de alto rendimiento, consulta la charla de Google I/O 2012 de Nat Duca y Tom Wiltzius del equipo de GPU de Chrome.