Cuando una aplicación se ralentiza, el instinto de la mayoría de los equipos es empezar a modificarla. Cambie una biblioteca, agregue un caché, actualice una máquina más grande. Es una reacción equivocada y costosa porque ataca los síntomas antes de comprender la enfermedad.
El rendimiento tiene un método. Hay un orden correcto de pasos y comienza mucho antes de tocar una línea de código. Este artículo es para aquellos que ya entienden que necesitan optimizar y quieren saber por dónde empezar de forma disciplinada, sin perder semanas en el lugar equivocado.
No voy a tratar esto como una lista de trucos. Los trucos resuelven casos específicos y envejecen rápidamente. El método resuelve cualquier caso y se sostiene a sí mismo.
Paso 0: Defina qué significa "rápido"
En primer lugar, responda: ¿qué es aceptable? "El sistema es lento" no es un problema solucionable. "La página de listado debe responder en menos de un segundo al 95% de las solicitudes".
Sin un objetivo, nunca se sabe cuándo parar. La optimización sin un objetivo es un agujero sin fondo, siempre puedes hacerlo más rápido y siempre cuesta más esfuerzo ganar menos. Definir límites de tiempo de respuesta aceptables, idealmente por percentiles, transforma una sensación difusa en un criterio objetivo.
Este paso parece burocrático, pero es lo que separa un esfuerzo de optimización de una búsqueda interminable. Y es tanto una conversación sobre productos y negocios como sobre ingeniería: lo que es "suficientemente rápido" depende de lo que el usuario esté tratando de hacer.
Paso 1: medir antes de revolver
La regla más importante de toda esta disciplina: no se optimiza lo que no se mide. Sin instrumentación, cualquier cambio es una conjetura, y las conjeturas surgen por suerte.
Instrumente la aplicación con métricas, registros estructurados e, idealmente, rastreo distribuido. El objetivo es responder a una pregunta sencilla: ¿dónde se gasta el tiempo? La respuesta casi siempre sorprende. El cuello de botella rara vez se encuentra donde señala la intuición.
Un patrón recurrente: el equipo jura que el problema es el lenguaje o marco, los instrumentos, y descubre que el 80% del tiempo está en una única consulta a la base de datos. Sin la medición, este equipo habría reescrito toda la aplicación y el problema seguiría ahí.
La herramienta importa menos que el hábito. Podría ser una solución completa de observabilidad o un registro bien ubicado. Lo que no puede faltar son los datos.
Paso 2: atacar primero el cuello de botella más grande
Con los datos en la mano, la priorización se vuelve obvia. Hay una poderosa regla general: la mayoría de las desaceleraciones tienden a deberse a una minoría de causas. Ataca primero al más grande.
Resiste la tentación de hacer diez microoptimizaciones que suman poco. Encuentre el elemento que por sí solo representa la mayor cantidad de tiempo y resuélvalo. El beneficio de eliminar el principal cuello de botella suele ser mayor que el de todas las demás mejoras combinadas.
Después de calcular el mayor, mida nuevamente. El cuello de botella se movió. El segundo mayor objetivo es ahora el nuevo objetivo. El desempeño es un proceso iterativo de medición, corrección y remediación, no un solo esfuerzo.
Paso 3: comience con la base de datos
En la mayoría de las aplicaciones empresariales, la banca es donde se pierde la mayor parte del tiempo. Por eso merece atención prioritaria. Tres comprobaciones resuelven una gran parte de los problemas:
- Índices faltantes. Consultas que escanean toda la tabla porque falta un índice en la columna filtrada. Es el error más común y el más barato de solucionar.
- El problema N+1. Cuando el código realiza una consulta para la lista y luego una consulta adicional para cada elemento de la lista. Cien artículos atendieron ciento una consultas. Se soluciona cargando los datos relacionados de una vez.
- Consultas que aportan demasiados datos. Buscar en toda la tabla para usar tres columnas es un desperdicio de base de datos, red y memoria.
Estas tres soluciones por sí solas transforman la percepción de velocidad en muchos sistemas. Y ninguno de ellos requiere un cambio de tecnología.
Paso 4: use el caché con prudencia
El caché es la optimización más seductora y peligrosa. Ofrece ganancias inmediatas e introduce toda una clase de errores nuevos: datos obsoletos.
La regla de oro: rizar sólo lo que pueda estar un poco viejo sin causar daños. Y siempre defina explícitamente cómo se invalidará el caché. El caché sin una estrategia de invalidación no es optimización, es una bomba de tiempo.
Para datos confidenciales, saldos, estado de pedidos, información que cambia y cuya precisión importa, piénselo dos veces. En los sistemas que tratan con dinero o decisiones ciudadanas, la exactitud de los datos gana a la velocidad. Mostrar un número incorrecto más rápido no ayuda a nadie.
También vale la pena recordar que el caché existe en varias capas: en el navegador del usuario, en la capa intermedia, en el servidor, en el banco. Cada uno resuelve un problema diferente y tiene su propio coste de invalidación. El error del principiante es apilar cachés sin entender cuál responde a qué, y luego, cuando un dato sale mal, nadie sabe en qué capa se quedó atascado. Mapear conscientemente dónde opera el caché es parte de usarlo bien.
Paso 5: solo entonces piensa en la infraestructura
Actualizar una máquina más grande o agregar más instancias suele ser el primer paso que dan los equipos. Debería ser uno de los últimos.
Ampliar la infraestructura sin arreglar primero el código y los cuellos de botella bancarios es tirar dinero al problema. Se paga más por hacer el mismo trabajo ineficiente, pero en paralelo. El costo crece y la ineficiencia sigue ahí, ahora más cara.
Cuando la optimización del código ya se ha realizado y el límite real es la capacidad, entonces entra en juego la infraestructura. Y la forma correcta casi siempre es escalar horizontalmente, agregar instancias, lo que requiere que la aplicación no tenga estado. Esta es una decisión arquitectónica que vale la pena tomar con anticipación, porque arreglarla más tarde es laboriosa.
El error que invalida todos los pasos
Hay un defecto cultural que sabotea cualquier guión: optimizar por intuición y celebrar sin medir el resultado. El equipo cambia algo, siente que se ha vuelto más rápido y sigue adelante. Sin medición después del cambio no sabes si mejoró, empeoró o no pasó nada.
Toda optimización necesita un antes y un después medibles. De lo contrario, simplemente estarás moviendo el código y retorciéndolo.
La reflexión honesta: la mayoría de los problemas de rendimiento no requieren genios ni herramientas costosas. Requiere disciplina. Mida, priorice, solucione el mayor cuello de botella, remedie. Los equipos que siguen este orden resuelven en días lo que los equipos que adivinan no pueden resolver en meses.
El desempeño bien logrado tiene menos que ver con el talento y más con el proceso. Quienes interiorizan estos pasos dejan de apagar incendios y empiezan a prevenirlos.
Si su equipo sigue resolviendo la lentitud en la oscuridad, quizás el problema no sea técnico, sino metodológico. Hay otros artículos en el blog sobre calidad, observabilidad y escalabilidad que complementan esta hoja de ruta. Si desea intercambiar ideas sobre cómo estructurar esto en su organización, vale la pena hablar.
Lea también
- Optimización del rendimiento móvil: los pasos esenciales para una aplicación que vuela
- Rendimiento del software: lo que enseñan casos reales sobre la calidad
- Consumo de batería en aplicaciones: cómo optimizar el rendimiento móvil
- Latencia en aplicaciones web: pasos esenciales de implementación
- Métricas de calidad del software: validación y pasos esenciales
- Pruebas automatizadas: por qué el código no probado es deuda