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

Introducción

Si eres de las personas que se mantienen al tanto de temas como cómo funcionan los navegadores, ya sabes que, últimamente, se publicaron algunos artículos increíbles que detallan la operación del renderizador/compuesto acelerado por GPU de Chrome. En primer lugar, Renderización acelerada en Chrome: el modelo de capas es una excelente introducción a cómo Chrome usa el concepto de capas para dibujar su página. Para un análisis más detallado, en Compilación acelerada por GPU en Chrome se explica cómo Chrome usa estas capas junto con la GPU para renderizar tu página.

La pregunta filosófica

Después de dedicar mucho tiempo a escribir rasterizadores de software para fines 3D, me pareció evidente que algunas propiedades de CSS deberían tener un rendimiento variado a la hora de dibujar 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 en una forma arbitraria. Entonces, la pregunta fue: ¿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 o valores de CSS según sus tiempos de pintura para que podamos comprender qué tipos de propiedades de CSS tienen un mejor rendimiento que otros. Para ello, escribí una automatización con cinta adhesiva y chicle para intentar agregar visibilidad numérica a los tiempos de pintura del CSS, que funcionó de la siguiente manera:

  • Genera un conjunto de páginas HTML individuales; cada una con un solo elemento del DOM y algunas permutaciones de propiedades CSS asociadas.
  • Ejecuta una secuencia de comandos de automatización que, para cada página, haga lo siguiente:
    • 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 la comparativa de Skia para obtener los tiempos
  • Elimina todos los tiempos y admira los números. (Esta parte es importante…)

Con esta configuración, generamos un conjunto de páginas HTML, en el que cada una 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, como una variante del último ejemplo, en la que solo cambiamos el valor del gradiente radial:

<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 afectados por estados inactivos en las cargas de página) 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 generaron 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 necesario para procesar esa página.

Evaluación de los datos

A partir de esto, ahora tenemos la capacidad aproximada de graficar cuánto tarda en pintarse un conjunto de propiedades de CSS. O mejor dicho, podemos comenzar a clasificar las propiedades de CSS según su rendimiento de pintura. Este es un gráfico grande tomado con la versión beta de Chrome 27 que muestra todo el conjunto completo de datos de tiempo de este proceso. Ten en cuenta que todos los datos están sujetos a cambios a medida que Chrome se vuelve más rápido con el tiempo.

Los tiempos de todas las permutaciones de la prueba

Cada barra vertical representa el tiempo de pintura de una página con una sola combinación de propiedades CSS (magnificada por 100 veces; el valor de escala real de este gráfico es de 0.156 ms). Hay muchas líneas bonitas, pero de esta forma es un poco inútil, ya que necesitamos analizar los datos para encontrar tendencias útiles.

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

El tiempo necesario para pintar un elemento que solo tiene 1 propiedad de CSS

En segundo lugar, y lo más interesante, las combinaciones de propiedades 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, ya que esperaríamos que A+B = C, no 2.2C. Por ejemplo, agrega box-shadow y border-radius-stroke:

Los 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, 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.

Los tiempos de todas las permutaciones de la prueba

Si observas los datos, verás que esto ocurre durante un tiempo. Hay muchas combinaciones extrañas, y mi suite de pruebas apenas las toca. Aún hay muchas pruebas y combinaciones que podrían generar 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 renderización de la página y cómo afecta la capacidad de respuesta de tu sitio. A continuación, se incluyen algunas sugerencias para comenzar.

  1. Usa el modo de pintura continua de Chrome en las Herramientas para desarrolladores de Chrome para comprender cuánto cuestan las propiedades de CSS.
  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 sepan que son más costosos, como gradientes y sombras. Pregúntate si realmente los necesitas.
  3. Cuando tengas dudas, siempre elige la opción que ofrezca un mejor rendimiento. Es posible que tus usuarios no recuerden el ancho del padding en tus columnas, pero sí recordarán lo que se siente al visitar tu sitio.

Conclusiones

Una de las cosas más interesantes de este experimento es que los tiempos seguirán cambiando con cada versión de Chrome (con suerte, serán más rápidos ;), ya que el software del navegador es una superficie en constante cambio. Lo que es lento hoy podría ser rápido mañana. Podrías evitar poner box-shadow: 1px 2px 3px 4px en un elemento que ya tiene border-radius:5. Sin embargo, la conclusión más valiosa debería ser que las propiedades CSS afectan directamente los tiempos de pintura de la página.

Referencias