wandres.dev
PERFORMANCE III · Diagnóstico por síntoma

La tabla de formas: si el perfil tiene esta silueta, mira aquí

El índice de diagnóstico por síntoma visual del panel de rendimiento, con la comprobación que confirma cada hipótesis y el error de leerlo al revés.

⏱ 18 min

Un perfil de rendimiento tiene una forma antes de tener números, y esa forma es diagnóstica. Un profesional con experiencia mira la silueta durante cinco segundos y ya sabe en qué familia está el problema, no porque tenga intuición mágica sino porque ha visto las mismas ocho o diez siluetas cientos de veces. Esta lección es esa experiencia escrita: la tabla que traduce forma a hipótesis, y la comprobación que convierte cada hipótesis en un hecho.

🎯 Al terminar esta lección sabrás
  • Clasificar un perfil en una de las familias de forma en menos de un minuto.
  • Aplicar la comprobación que confirma o descarta cada hipótesis.
  • Ordenar las hipótesis por probabilidad antes de invertir tiempo en ninguna.
  • Reconocer las formas que parecen problemas y no lo son.

La tabla

La columna que importa es la tercera: una hipótesis sin comprobación es una opinión, y las opiniones sobre rendimiento son casi siempre falsas.

Forma del perfil Hipótesis Comprobación que la confirma
Un bloque enorme y continuo de script al principio Coste de arranque, paquete grande o hidratación Mirar el nombre del fichero en el gráfico y su tamaño en red
Franjas alternas de estilo y disposición dentro de un script Disposición sincrónica forzada en bucle Buscar la marca de reflujo forzado y el enlace a la línea
Muchas tareas cortas iguales, muy repetidas Trabajo por elemento en una colección grande Contar apariciones en la vista de abajo arriba
Una tarea larga aislada tras una respuesta de red Procesamiento de la respuesta sin trocear Comprobar el tamaño del cuerpo y el instante de llegada
Pistas del compositor y la GPU llenas, hilo principal vacío Demasiadas capas o superficies muy grandes Bordes de capa y el contador de capas
Pintado alto y continuo sin cambios visibles Repintado excesivo por elementos mal aislados Resaltado de repintado en el panel de renderizado
Hilo principal vacío y usuario esperando Espera de red, otro proceso, o extensión Cruzar con la pista de red y probar sin extensiones
Fotogramas regulares que se degradan con el tiempo Fuga de memoria o crecimiento de estructuras Comparar dos perfiles separados por varios minutos
Tareas largas en un dominio de terceros Script externo pesado Filtrar el gráfico por dominio
Gráfico dominado por una función de framework Renderizado excesivo o falta de memoización Contar montajes con las herramientas del framework
⚠️
Cuidado

La tabla se lee en un sentido y no en el otro. De la forma a la hipótesis, funciona. De la hipótesis a la forma, no: convencerse de que el problema es de disposición forzada y buscar franjas alternas hasta encontrar dos es el mecanismo por el que se confirma cualquier teoría en cualquier perfil. Mira primero, formula después.

Cómo se mira la forma

La forma se aprecia con el rango completo y el gráfico alejado, no con el zoom puesto. El detalle destruye la silueta. El procedimiento son cuatro miradas de diez segundos cada una.

La primera al reparto de colores del resumen. Un perfil dominado por amarillo de script, por morado de estilo y disposición, o por verde de pintado son tres mundos distintos. Este reparto solo es un dato con el rango bien acotado: el reparto de una grabación de veinte segundos donde el problema dura trescientos milisegundos no dice nada.

La segunda a la densidad y a la longitud de las tareas. ¿Pocas y largas, o muchas y cortas? Es la distinción entre un problema de bloqueo y uno de volumen, y tienen arreglos opuestos: partir en un caso, reducir el número en el otro.

La tercera a la relación entre el hilo principal y las demás pistas. ¿Está el hilo principal ocupado mientras el usuario espera, o está vacío? Un hilo vacío con el usuario esperando es un diagnóstico completamente distinto y descarta de golpe media tabla.

La cuarta a la periodicidad. ¿Hay un patrón que se repite a intervalos regulares? La periodicidad delata temporizadores, sondeos y suscripciones, y es una forma que se reconoce de un vistazo y que se busca durante horas si no se mira a propósito.

Las formas que parecen problemas y no lo son

Cuatro siluetas alarmantes que son perfectamente normales y que hacen perder tiempo a quien no las reconoce.

El hilo principal saturado durante el arranque. Una aplicación grande va a ejecutar mucho JavaScript al arrancar. Eso solo es un problema si retrasa el primer contenido útil o si bloquea interacciones tempranas. La pregunta no es si el hilo está ocupado sino si alguien estaba esperando.

Muchos fotogramas largos durante una animación de entrada. Si la animación dura trescientos milisegundos y ocurre una vez al cargar, un par de fotogramas perdidos no los percibe nadie. Los fotogramas perdidos importan en interacción continua: desplazamiento, arrastre, movimiento sostenido.

Un pico de trabajo justo después de un clic. Es el trabajo del clic. Solo es un problema si retrasa la respuesta visible, y para eso está el desglose de la interacción.

Actividad periódica de baja intensidad. Un temporizador que consume dos milisegundos cada segundo es visible en el perfil, tiene una forma muy reconocible y es completamente irrelevante. Que algo se vea no significa que cueste.

El criterio que unifica los cuatro casos: una forma es un problema cuando coincide en el tiempo con alguien esperando. Sin esa coincidencia es solo actividad.

Confirmar antes de arreglar

Cada hipótesis necesita una comprobación barata que la mate o la confirme, y el orden importa: intentar confirmar lo más probable primero es más lento que intentar descartar lo más barato primero.

// Comprobaciones rapidas que descartan o confirman las hipotesis mas comunes
(() => {
  const r = {};

  // Volumen de DOM: descarta o confirma coste estructural
  r.elementos = document.querySelectorAll('*').length;
  r.reglasCSS = [...document.styleSheets].reduce((s, h) => {
    try { return s + h.cssRules.length; } catch { return s; } }, 0);

  // Peso y numero de scripts, y cuanto es de terceros
  const recursos = performance.getEntriesByType('resource');
  const scripts = recursos.filter(e => e.initiatorType === 'script');
  const propios = scripts.filter(e => new URL(e.name).origin === location.origin);
  r.scripts = scripts.length;
  r.scriptsDeTerceros = scripts.length - propios.length;
  r.kbScripts = Math.round(scripts.reduce((s, e) => s + (e.encodedBodySize || 0), 0) / 1024);
  r.kbTerceros = Math.round(scripts.filter(e => new URL(e.name).origin !== location.origin)
    .reduce((s, e) => s + (e.encodedBodySize || 0), 0) / 1024);

  // Temporizadores activos: delata la periodicidad
  let contadorIntervalos = 0;
  const originalSetInterval = window.setInterval;
  window.setInterval = function (...args) { contadorIntervalos++; return originalSetInterval.apply(this, args); };
  setTimeout(() => {
    console.log('Intervalos creados desde que se cargo este snippet:', contadorIntervalos);
    window.setInterval = originalSetInterval;
  }, 10000);

  // Capas de composicion: aproximacion por propiedades que las provocan
  const promotores = [...document.querySelectorAll('*')].filter(el => {
    const s = getComputedStyle(el);
    return s.willChange !== 'auto' || s.transform !== 'none' ||
           s.filter !== 'none' || s.position === 'fixed';
  });
  r.candidatosACapa = promotores.length;

  console.table([r]);
  if (r.elementos > 5000) console.warn('Arbol grande: sospecha de coste de estilo y disposicion.');
  if (r.kbTerceros > r.kbScripts / 2) console.warn('Mas de la mitad del JavaScript es de terceros.');
  if (r.candidatosACapa > 60) console.warn('Muchos candidatos a capa: revisa el compositor.');
})();

Ninguna de estas comprobaciones demuestra nada por sí sola; todas descartan. Un árbol de mil doscientos elementos descarta la hipótesis de coste estructural y ahorra media hora de investigación en la dirección equivocada, que es exactamente el valor de una comprobación barata.

La forma sirve para elegir dónde mirar, y el error es dejar que también elija la conclusión

El uso correcto del reconocimiento de siluetas es como filtro de entrada, y el modo de fallo es dejar que funcione como veredicto. La diferencia es sutil en el momento y enorme en el resultado. Cuando una silueta te dice “esto parece disposición forzada”, lo que ha ocurrido es que has reducido el espacio de búsqueda de veinte hipótesis a tres, lo cual es un avance enorme y absolutamente legítimo. Lo que no ha ocurrido es que sepas la causa. El paso que se salta la gente con prisa es la comprobación, y sin ella la forma se convierte en una profecía autocumplida: encuentras el patrón que buscabas porque en cualquier perfil de una aplicación real hay ejemplos de casi todo. Hay una asimetría que conviene explotar y que casi nadie usa deliberadamente: descartar es mucho más barato que confirmar, y sin embargo casi todo el mundo intenta confirmar primero. Confirmar que el problema es la disposición forzada exige encontrar la línea, entenderla, medirla y demostrar que su coste explica el síntoma; media hora larga. Descartarla cuesta veinte segundos: si el reparto de colores del resumen apenas tiene morado, no es eso, y te acabas de ahorrar la media hora. La estrategia óptima es por tanto recorrer la tabla al revés de como la intuición pide: haz primero las tres comprobaciones más baratas, aunque correspondan a las hipótesis que te parecen menos probables, porque cada una que elimines reduce el espacio y ninguna te cuesta nada. Cuando queden dos o tres hipótesis vivas, entonces sí, invierte en confirmar la más probable. Es el mismo principio de bisección que gobierna toda la depuración, aplicado a un espacio de hipótesis en vez de a un espacio de código, y es lo que hace que alguien resuelva en veinte minutos lo que a otro le cuesta un día: no mira mejor, descarta más rápido.