Tiempos de procesamiento de CSS y peso de renderización de la página

Introducción

Si eres el tipo de persona que se mantiene al tanto de cosas como cómo funcionan los navegadores, ya sabes que últimamente se publicaron algunos artículos increíbles que detallan la operación de renderizador/compuesto acelerado por GPU de Chrome. En primer lugar, Accelerated Rendering in Chrome: The Layer Model es una excelente introducción a cómo Chrome usa el concepto de capas para dibujar su página. Para un estudio a fondo, consulta GPU Accelerated Compositing in Chrome, donde se analiza cómo Chrome usa estas capas, junto con la GPU, para renderizar tu página.

La pregunta filosófica

Después de pasar mucho tiempo escribiendo rasterizadores de software para fines de 3D, me di cuenta de que algunas propiedades de CSS deberían tener un rendimiento variado cuando se dibuja tu página. Por ejemplo, rasterizar una imagen pequeña en la pantalla es una operación algorítmica completamente diferente a dibujar una sombra paralela en una forma arbitraria. Entonces, la pregunta es: ¿Cómo afectan las diferentes propiedades de CSS al peso de renderización de tu página?

Mi objetivo era categorizar un gran conjunto de propiedades y valores de CSS según sus tiempos de pintura, de modo que podamos comprender qué tipos de propiedades de CSS tienen un mejor rendimiento que otras. Para ello, escribí una automatización con cinta adhesiva y goma de mascar para intentar agregar visibilidad numérica a los tiempos de pintura de CSS, que funcionó de la siguiente manera:

  • Genera un conjunto de páginas HTML individuales, cada una con un solo elemento del DOM y alguna permutación de propiedades de CSS adjuntas.
  • Ejecuta una secuencia de comandos de automatización que, para cada página, realice las siguientes acciones:
    • Iniciar Chrome
    • Carga una página
    • Produce una imagen de Skia para la página.
    • Ejecuta cada imagen de Skia tomada a través de Skia Benchmark para obtener los tiempos.
  • Vuelca todos los tiempos y maravíllate con los números. (Esta parte es importante…)

Con esta configuración, generamos un conjunto de páginas HTML, en las que cada página contiene una permutación única de propiedades y valores de CSS. Por ejemplo, aquí hay dos archivos HTML:

<style>
#example1 {
    background: url(foo.png) top left / 50% 60%;
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

Y otro, que es más complejo

<style>
#example1 {
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(circle closest-corner, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

A continuación, se muestra una variante del último ejemplo, en el que solo cambiamos el valor de radial-gradient:

<style>
#example1 
{
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(farthest-side, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1" style="padding: 20px; margin-top: 10px;margin-right: 20px; text-align: center;">WOAH</div>

Luego, cada página se carga en una instancia nueva de Chrome (para garantizar que los tiempos no se vean sesgados de alguna manera por estados inactivos en las recargas de páginas) y se toma una imagen de Skia (*.SKP) para evaluar qué comandos de Skia se usan para pintar la página. Una vez que se generan los archivos SKP para cada archivo HTML, ejecutamos otro lote para enviar los archivos *.SKP a través de la aplicación Skia Benchmark (compilada a partir del código fuente de Skia), que vuelca el tiempo promedio que se tarda en renderizar esa página.

Evalúa los datos

A partir de esto, ahora tenemos una capacidad aproximada para trazar cuánto tarda en pintarse un conjunto de propiedades de CSS. O, mejor dicho, podemos empezar a clasificar las propiedades de CSS según su rendimiento de pintura. Aquí tienes un gráfico grande tomado con Chrome 27 beta que muestra todo el conjunto de datos de tiempo de este proceso. Ten en cuenta que todos los datos están sujetos a cambios, ya que Chrome se vuelve cada vez más rápido con el tiempo.

Tiempos de todas las permutaciones de la prueba

Cada barra vertical representa el tiempo de renderización de una página con una sola combinación de propiedades de CSS (ampliado 100 veces; el valor de escala real de este gráfico es de 0 a 1.56 ms). Hay muchas líneas bonitas, pero en esta forma es algo inútil; necesitamos hacer algo de minería de datos para encontrar tendencias útiles.

En primer lugar, encontramos pruebas de que algunas propiedades de CSS son simplemente más costosas de renderizar que otras. Por ejemplo, dibujar una sombra paralela en un elemento del DOM implica una operación de varios pasos con splines y otros tipos de cosas desagradables, a diferencia de la opacidad, que debería ser más fácil de renderizar.

Tiempo que se tarda en pintar un elemento que solo tiene 1 propiedad de CSS

En segundo lugar, y lo que es más interesante, las combinaciones de propiedades de CSS pueden tener un tiempo de pintura mayor que la suma de sus partes. Desde la perspectiva de un observador, esto es un poco extraño, esperaríamos que A+B = C, no 2.2C. Por ejemplo, agrega box-shadow y border-radius-stroke :

Tiempos de todas las permutaciones de la prueba

Lo que es realmente interesante de esto es que no se trata solo de la propiedad box-shadow en sí, sino de esa permutación de valor específica. Por ejemplo, a continuación, se muestra una agrupación de box-shadow : 50% y border-radius con variaciones de valor.

Tiempos de todas las permutaciones de la prueba

Si observamos los datos, esto continúa por un tiempo. Hay muchas combinaciones extrañas, y mi paquete de pruebas apenas las toca todas; todavía hay toneladas de pruebas y combinaciones que podrían arrojar resultados interesantes.

Cómo encontrar el peso de renderización de tu página

Con la capacidad de hacer un seguimiento de los tiempos de renderización de cada elemento de tu página, los desarrolladores pueden comenzar a evaluar el peso de la renderización de la página y cómo afecta la capacidad de respuesta de tu sitio. Aquí tienes un par de sugerencias para comenzar:

  1. Usa el modo de pintura continua de Chrome en las Herramientas para desarrolladores de Chrome para comprender qué propiedades de CSS te están costando.
  2. Incorpora revisiones de CSS en tu proceso de revisión de código existente para detectar problemas de rendimiento. Busca lugares en tu CSS en los que uses elementos que se sabe que son más costosos, como gradientes y sombras. Pregúntate: ¿De verdad necesito esto aquí?
  3. En caso de duda, siempre opta por un mejor rendimiento. Es posible que tus usuarios no recuerden el ancho del relleno de las columnas, pero sí recordarán cómo se siente visitar tu sitio.

Reflexiones finales

Uno de los aspectos más interesantes de este experimento es que los tiempos seguirán cambiando con cada versión de Chrome (esperamos que sean más rápidos; el software del navegador es un área de superficie en constante cambio). Lo que hoy es lento, mañana podría ser rápido. Puedes quitar de este artículo para evitar colocar box-shadow: 1px 2px 3px 4px en un elemento que ya tiene border-radius:5. Sin embargo, la conclusión más importante debería ser que las propiedades de CSS afectan directamente los tiempos de renderización de la página.

Referencias