# Mide primero, luego hazlo rápido

Curso exprés sobre rendimiento. 20 conceptos — Profiling, Latency, Throughput, Batching, Bottleneck, Amdahl's Law, Big-O, N+1 Query, Caching, Percentiles, Tail Latency, Premature Optimization y más — cada uno con su nombre en inglés, un diagrama y una ficha: qué es → cómo funciona → ejemplo → trampa. Una chuleta al final. La idea central: la intuición sobre la lentitud suele equivocarse, así que haz profiling, arregla lo único que domina y vuelve a medir.

- **Author:** Fedor Chishchin
- **Level:** intermediate
- **Reading time:** ~35 minutos de lectura
- **Published:** 2026-06-13
- **Source:** https://fedorthinks.com/es/learn/performance-express

---

## 1. Mide, no adivines

La primera regla del rendimiento es la que todo el mundo rompe: no te fíes de tu corazonada sobre qué es lento. Casi toda la optimización malgastada viene de saltarse este único paso.

### Tu intuición sobre la lentitud suele equivocarse

> Un médico que prescribe cirugía basándose en una corazonada, sin haber hecho nunca una prueba — seguro, rápido y, con demasiada frecuencia, operando algo que no era el problema.

Los desarrolladores son famosos por adivinar mal dónde se va el tiempo. La parte que crees lenta a menudo está bien; el verdadero culpable está en un sitio que nunca sospechaste — una función diminuta llamada un millón de veces, una llamada oculta a la base de datos.

Actuar por corazonada significa que optimizas lo que no toca, añades complejidad y el programa sigue siendo lento. El primer movimiento nunca es «arréglalo» — es **averiguar adónde se va realmente el tiempo.**

### El mapa: 20 conceptos en siete grupos

> Un mapa de metro: primero ves las líneas enteras, luego recorres estación por estación.

Los conceptos del curso se dividen en siete grupos — uno por capítulo. Primero, cómo medir. Luego, qué tipo de «rápido» necesitas. Después, el bottleneck y los arreglos clásicos para él. Y por último, cómo no dejarte engañar por el promedio, cuándo no optimizar y cómo llevar todo esto como un bucle.

_Diagram: Siete grupos de conceptos — los capítulos del curso los siguen._

### Cómo leer este curso

> Un mecánico no cambia piezas al azar: primero los instrumentos, luego un arreglo, luego una nueva prueba.

Cada concepto recibe el mismo tratamiento: su **nombre en inglés** (memorízalo — es el término de la documentación, los profilers y los paneles), una imagen de la vida cotidiana, un **diagrama** y una **ficha** con _qué es_, _cómo funciona_, _ejemplo_, _trampa_ y _relaciones_.

La gran idea: el rendimiento no es una bolsa de trucos, es un método. **Mide → encuentra el bottleneck → arregla esa única cosa → vuelve a medir → para al llegar al objetivo.** Todo lo demás del curso son detalles dentro de ese bucle.

### Profiling — encuentra el coste real

> Una factura detallada que muestra exactamente adónde se fue el dinero, línea por línea — para que dejes de adivinar y veas que fue ese cargo, no los que suponías, el que se comió el presupuesto.

Un **profiler** es una herramienta que mide dónde gasta realmente el tiempo tu programa, función por función. Convierte «creo que esto es lento» en «esta función es el 80% del tiempo de ejecución». Con eso, arreglas lo que importa en lugar de lo que imaginabas.

Ya sea un profiler, logs de tiempos o tus métricas de **observabilidad**, el principio se mantiene: **deja que la medición, no la intuición, te señale el problema.**

_Diagram: Un profile muestra la parte del tiempo de cada función. Sospechabas del renderizado (8%); una sola consulta a la base de datos se come el 80%._

#### Profiling (profiler)

- **Qué es:** Medir dónde gasta realmente el tiempo un programa, función por función.
- **Cómo funciona:** Un profiler (o logs de tiempos, o métricas) registra el tiempo de cada parte y muestra las proporciones.
- **Ejemplo:** «`getOrders()` es el 80% de la petición» en lugar de «el renderizado debe de ser lento».
- **Trampa:** Un profile con datos de juguete puede apuntar en la dirección equivocada — mide con una carga realista.
- **Relaciones:** El primer paso de **Measure–Fix–Measure**; es lo que encuentra el **Bottleneck**.

### Measure–Fix–Measure — mide, arregla, vuelve a medir

> Un científico cambia una variable, repite el experimento y comprueba el resultado — nunca da por hecho que un cambio ayudó, siempre confirma que así fue.

El rendimiento es un bucle: mide para encontrar la parte lenta, cámbiala y **vuelve a medir** para confirmar que el cambio ayudó de verdad — y que no se limitó a mover el problema o a empeorarlo.

Sin la segunda medición estás adivinando si mejoraste algo, que es como las «optimizaciones» empeoran las cosas en silencio. Trata cada arreglo como una **hipótesis** que verificas — la misma disciplina que las evals para la IA o los tests para el código.

_Diagram: Mide → cambia una cosa → mide con la misma prueba. Más rápido — te lo quedas; no más rápido — lo reviertes._

#### Measure–Fix–Measure (mide, arregla, vuelve a medir)

- **Qué es:** Cada arreglo se comprueba con una segunda medición, antes y después.
- **Cómo funciona:** La misma prueba antes y después; cambia una cosa a la vez para saber qué funcionó.
- **Ejemplo:** Añadiste un índice: la consulta pasó de 400 ms a 40 ms — te lo quedas. Sin cambio — lo reviertes.
- **Trampa:** Sin la segunda medición, una «optimización» puede ralentizar el sistema en silencio y nadie lo nota.
- **Relaciones:** El núcleo del **Optimization Loop**; primo de las evals y los tests.

> **La pregunta de encuadre:** «¿He medido de verdad adónde se va el tiempo — o estoy a punto de optimizar algo basándome en una corazonada que probablemente apunta al lugar equivocado?»

> La intuición sobre la lentitud suele equivocarse. Haz profiling para encontrar adónde se va realmente el tiempo, arréglalo y vuelve a medir para confirmar — nunca optimices por una corazonada.

## 2. Latency y throughput

Antes de optimizar, sabe qué tipo de «rápido» quieres en realidad. Dos objetivos distintos se confunden constantemente, y mejorar uno puede no hacer nada por el otro.

### Latency — la espera por una sola cosa

> Cuánto tarda un solo café desde el pedido hasta la taza — la experiencia de un cliente, medida de principio a fin.

La **latency** es cuánto tarda una operación de principio a fin — una petición, una carga de página, una consulta. Es lo que un usuario individual _siente_: la espera.

Cuando alguien dice «el sitio es lento», casi siempre se refiere a la latency — el retraso entre hacer algo y obtener una respuesta. Bajar la latency es hacer que cada cosa individual ocurra más rápido.

_Diagram: La latency es todo el camino de una petición: red, trabajo del servidor, red de vuelta, renderizado._

#### Latency (tiempo de respuesta)

- **Qué es:** El tiempo de una operación de principio a fin, normalmente en milisegundos.
- **Cómo funciona:** Suma todos los pasos del camino: red, trabajo del servidor, base de datos, renderizado.
- **Ejemplo:** Desde el clic hasta la página lista — 800 ms.
- **Trampa:** Un único número de latency suele ser un promedio, y el promedio esconde los casos lentos (capítulo 5).
- **Relaciones:** Un objetivo distinto del **Throughput**; se mide con **Percentiles**.

### Throughput — cuánto manejas por segundo

> Cuántos cafés sirve la cafetería entera en una hora — no cuánto tarda uno, sino el flujo total a través del local.

El **throughput** es cuánto trabajo maneja el sistema por unidad de tiempo — peticiones por segundo, trabajos por minuto. Tiene que ver con la capacidad total, no con la espera individual.

Un sistema puede tener un gran throughput (sirviendo a miles a la vez) mientras cada usuario aún espera un rato (latency alta), o latency baja pero capacidad limitada. Son objetivos distintos, y cuál persigues cambia lo que arreglas.

_Diagram: El throughput es el flujo total del sistema: cuántas peticiones por segundo logra sacar adelante._

#### Throughput (peticiones por segundo)

- **Qué es:** Trabajo hecho por unidad de tiempo: peticiones por segundo, trabajos por minuto.
- **Cómo funciona:** Sube cuando el sistema maneja más en paralelo o gasta menos en cada unidad.
- **Ejemplo:** Una API maneja 1.000 peticiones por segundo; un pipeline nocturno, un millón de filas por hora.
- **Trampa:** Un throughput alto no significa una experiencia rápida: cada usuario aún puede esperar mucho.
- **Relaciones:** A menudo se sube a costa de la **Latency** mediante **Batching**.

### Batching — throughput a costa de latency

> Una moto te lleva más rápido (latency baja); un autobús mueve a más gente por viaje (throughput alto). El mejor vehículo depende de lo que necesites.

Latency y throughput son independientes, y optimizar uno puede perjudicar al otro. El **batching** — agrupar el trabajo — suele subir el throughput pero añade latency, porque cada elemento espera al lote.

Así que tienes que decidir cuál importa aquí: una página de cara al usuario vive o muere por la latency; un pipeline de datos en segundo plano se preocupa por el throughput. Nombrar tu objetivo real evita que optimices el número que no le importa a tus usuarios.

_Diagram: Uno a uno — cada elemento sale enseguida, pero hay muchos viajes. En lote — un viaje, más por segundo, pero cada elemento espera al lote._

#### Batching (agrupar el trabajo)

- **Qué es:** Reunir muchas operaciones pequeñas en una grande.
- **Cómo funciona:** El coste fijo (un viaje por la red, arrancar un trabajo) se paga una vez por lote, no una vez por elemento.
- **Ejemplo:** Insertar 1.000 filas en una consulta en lugar de 1.000 consultas separadas.
- **Trampa:** Cada elemento espera a que se llene el lote — la latency sube.
- **Relaciones:** Cambia **Latency** por **Throughput**; la misma idea que cura el **N+1 Query**.

> **La pregunta del objetivo:** «¿Intento que cada operación se sienta más rápida (latency) o que se maneje más volumen total (throughput)? Son cosas distintas, y el arreglo de una puede no ayudar a la otra.»

> La latency es la espera por una operación; el throughput es cuánto manejas por segundo. Son objetivos independientes — y el batching suele cambiar latency por throughput.

## 3. Encuentra el bottleneck

El rendimiento no se reparte por igual. Casi siempre, una parte domina el tiempo — y optimizar cualquier otra cosa es esfuerzo perdido hasta que arregles esa.

### Bottleneck — una parte lenta domina

> Una cadena es tan fuerte como su eslabón más débil — reforzar los eslabones fuertes no sirve de nada; solo el débil decide si aguanta.

En la mayoría de los sistemas lentos, un único **bottleneck** se lleva la mayor parte del tiempo — una consulta, un servicio lento, un bucle malo. Todo lo demás ya es lo bastante rápido.

Por eso adivinar es tan inútil: toda la habilidad consiste en localizar el **coste dominante**, no en mejorar las partes rápidas.

_Diagram: La petición pasa por cinco pasos, pero 400 ms de los 500 son una sola consulta a la base de datos. Ese es el bottleneck._

#### Bottleneck (el coste dominante)

- **Qué es:** La única parte que se lleva la mayor parte del tiempo total.
- **Cómo funciona:** Un profile muestra las proporciones; normalmente una parte es mucho mayor que el resto.
- **Ejemplo:** Una página tarda 500 ms, y 400 son una consulta sobre una columna sin índice.
- **Trampa:** El bottleneck rara vez está donde lo esperas — por eso, primero profiling.
- **Relaciones:** Se encuentra con **Profiling**; la **Amdahl's Law** explica por qué es lo que hay que arreglar.

### Limiting Step — el sistema es tan rápido como su paso más lento

> Una autopista despejada hasta que un carril cortado hace que todos los coches avancen a paso de tortuga — la velocidad de todo el viaje la marca ese único cuello de botella, no los tramos libres.

Una petición que pasa por diez pasos está limitada por el más lento — el **limiting step**. Acelerar los nueve pasos rápidos apenas mueve el total; el paso lento marca el ritmo. Así que apuntas al cuello de botella en concreto.

Y fíjate en que arreglar un bottleneck a menudo _revela_ el siguiente: quita el paso más lento y aparece uno nuevo. El trabajo de rendimiento es encontrar y despejar, una y otra vez, lo que limita al sistema _ahora mismo_.

_Diagram: Arreglada la consulta: 500 → 140 ms. Ahora el renderizado es el paso más lento, y la siguiente ronda apunta a él._

#### Limiting Step (el siguiente bottleneck)

- **Qué es:** El paso que ahora mismo marca la velocidad de todo el camino.
- **Cómo funciona:** Quita un limiting step y el siguiente más lento pasa a serlo.
- **Ejemplo:** La consulta se hizo 10× más rápida — ahora 50 ms de renderizado son el paso más lento.
- **Trampa:** El bottleneck nunca desaparece del todo, se mueve — por eso necesitas un objetivo en el que parar.
- **Relaciones:** Por qué el **Optimization Loop** es un bucle, y por qué el **Performance Target** es su salida.

### Amdahl's Law — optimizar en otro sitio es esfuerzo perdido

> Sacar brillo al trofeo mientras el coche tiene un pinchazo — esfuerzo gastado donde no cambia nada, mientras lo que de verdad te detiene queda ignorado.

Optimiza una parte que es solo el 2% del tiempo de ejecución y lo máximo que ganarás es un 2%. Encuentra la parte que es el 80% y arreglarla lo transforma todo. Esta aritmética se llama **ley de Amdahl**: tu ganancia está limitada por la proporción de tiempo que ocupa la parte que aceleras.

El tiempo dedicado a optimizar cualquier cosa que no sea el bottleneck es, por definición, tiempo que no puede ayudar de forma significativa. A menudo empeora las cosas, añadiendo complejidad y errores por una ganancia invisible. La medición te impide optimizar con cariño la parte que entiendes y te obliga a ir a la que de verdad cuesta. **Arregla el bottleneck, ignora el resto** — hasta que el resto se convierta en el bottleneck.

_Diagram: Haz el renderizado 2× más rápido — menos 5%. Haz la consulta 2× más rápida — menos 40%. La ganancia está limitada por la proporción de la parte._

#### Amdahl's Law (la ganancia está limitada por la proporción)

- **Qué es:** Acelerar una parte de un sistema está limitado por la proporción de tiempo que ocupa esa parte.
- **Cómo funciona:** Una parte que es el 10% del tiempo puede ahorrar como mucho un 10%, aunque se hiciera infinitamente rápida.
- **Ejemplo:** Renderizado (10%) 2× más rápido: 500 → 475 ms. La consulta (80%) 2× más rápida: 500 → 300 ms.
- **Trampa:** Sienta bien optimizar lo que entiendes — pero si no es el bottleneck, no hay ganancia.
- **Relaciones:** Las matemáticas detrás del **Bottleneck**; el argumento contra la **Premature Optimization**.

> **La pregunta del bottleneck:** «¿Qué única parte domina el tiempo aquí — y estoy arreglando esa, o sacando brillo a una parte que ya es lo bastante rápida como para que apenas importe?»

> Un bottleneck suele dominar el tiempo, y el sistema es tan rápido como su paso más lento. Arregla esa única cosa; optimizar cualquier otra es esfuerzo perdido hasta que se convierta en el bottleneck.

## 4. Las mayores victorias

Cuando encuentras el bottleneck, el arreglo suele ser uno de un puñado de clásicos. Estos pocos explican la inmensa mayoría de las aceleraciones reales.

### Better Algorithm (Big-O) — un mejor algoritmo vence a una máquina más rápida

> Dos rutas a la misma ciudad: un coche más rápido por la carretera larga y sinuosa pierde ante un coche más lento por el atajo recto. La ruta importa más que el motor.

Las mayores victorias suelen venir de un mejor **algoritmo** o estructura de datos, no de hardware más rápido ni de microajustes. **Big-O** describe cómo crece el tiempo al crecer la entrada. Un bucle **O(n²)** sustituido por una búsqueda en un mapa hash **O(n)** puede convertir minutos en milisegundos — un cambio que ninguna máquina más rápida igualaría.

Antes de optimizar lo pequeño, pregúntate si el _enfoque_ es el equivocado. Una mejor forma, como muestra el curso de estructuras de datos, es la aceleración más barata y más grande que existe.

_Diagram: O(n²) se dispara al crecer la entrada; O(n) crece de forma constante. Con datos grandes es la diferencia entre minutos y milisegundos._

#### Better Algorithm (Big-O, complejidad algorítmica)

- **Qué es:** Cambiar el enfoque para que el trabajo crezca más despacio con los datos.
- **Cómo funciona:** Big-O muestra el crecimiento: O(n²) es un bucle anidado de «todos con todos», O(n) es una sola pasada.
- **Ejemplo:** Encontrar los elementos comunes de dos listas: bucle anidado → un hash set y una sola pasada.
- **Trampa:** Con pocos datos no se nota la diferencia — explota al crecer los datos.
- **Relaciones:** La elección principal de **Performance by Design**; mira el curso de estructuras de datos.

### N+1 Query — demasiados viajes de ida y vuelta

> Hacer veinte viajes distintos a la tienda para comprar una cosa cada vez, en lugar de uno solo con una lista — el trayecto, no la compra, se está comiendo tu tarde.

Una enorme cantidad de lentitud son **demasiados viajes de ida y vuelta** — llamadas repetidas a una base de datos o a un servicio, cada una barata por sí sola pero devastadora en masa.

El clásico es la **N+1 query**: traer una lista y luego hacer una consulta más por cada elemento, convirtiendo un viaje en cientos. El arreglo es **traer en bloque** — pedirlo todo de una vez. Reducir el _número_ de viajes suele superar a acelerar cada uno, porque el viaje en sí es el coste.

_Diagram: Izquierda: 1 consulta para la lista + N consultas una por una. Derecha: una sola consulta para todo._

#### N+1 Query (viajes de ida y vuelta de más)

- **Qué es:** Una consulta para una lista y luego una consulta por cada elemento.
- **Cómo funciona:** Cada viaje a la base de datos cuesta red y sobrecarga; N viajes multiplican ese coste por N.
- **Ejemplo:** 100 pedidos → 1 consulta para la lista + 100 consultas para los clientes. Arreglo: una consulta con `IN (…)` o un JOIN.
- **Trampa:** Los ORM lo esconden: el código parece un bucle simple, y por debajo hay cientos de consultas.
- **Relaciones:** Se cura con la misma idea que el **Batching**; un **Bottleneck** frecuente.

### Caching — no calcules lo mismo dos veces

> Volver a cocinar una comida desde cero cada vez que alguien la pide, en lugar de mantener una olla caliente — el trabajo más rápido es el que no repites.

El **caching** — recordar un resultado costoso para no recalcularlo — es una de las mayores palancas que existen (tiene su propio curso).

La primera petición toma el camino lento y guarda el resultado; las siguientes lo obtienen de la memoria. El precio es memoria y el riesgo de servir datos desactualizados.

_Diagram: Un hit se responde desde la memoria. Un miss toma el camino lento y recuerda el resultado para la próxima vez._

#### Caching (recordar resultados costosos)

- **Qué es:** Guardar el resultado de un trabajo costoso y servirlo de nuevo.
- **Cómo funciona:** Mira la caché: está — se devuelve al instante (hit); no está — se calcula, se guarda, se devuelve (miss).
- **Ejemplo:** Una página de catálogo tarda 300 ms en construirse; desde la caché, un par de milisegundos.
- **Trampa:** Una caché puede servir datos desactualizados; cuándo vaciarla es un problema difícil por sí mismo.
- **Relaciones:** Un caso especial de **Doing Less**; tratado a fondo en el curso de caching.

### Doing Less — el trabajo más rápido es el que te saltas

> No cocinar lo que nadie pidió, y no poner la mesa para veinte cuando han venido tres.

Otro clásico más — **hacer menos**. Calcula las cosas de forma **perezosa (lazy)**, solo cuando de verdad hacen falta; evita cargar datos que no vas a usar; sáltate el trabajo cuyo resultado vas a tirar.

La operación más rápida es la que nunca ejecutas. A menudo la mejor optimización no es hacer el trabajo más rápido — es no hacerlo en absoluto.

_Diagram: Solo una parte de todo el trabajo hace falta de verdad. El resto son datos sin usar, trabajo hecho demasiado pronto y resultados que se tiran._

#### Doing Less (evaluación perezosa (lazy))

- **Qué es:** Quitar trabajo en lugar de acelerarlo.
- **Cómo funciona:** Cálculo perezoso, cargar solo los campos que necesitas, descartar resultados que nadie usa.
- **Ejemplo:** Saca de la base de datos los 3 campos que necesitas, no los 50; construye un informe solo cuando se abre.
- **Trampa:** El trabajo perezoso puede morder más tarde, en un momento incómodo — mide.
- **Relaciones:** Incluye **Caching** (no repetir) y cura parte del **N+1 Query**.

> **La pregunta de las victorias:** «¿El bottleneck es un mal algoritmo, demasiados viajes de ida y vuelta, falta de caching o trabajo que podría saltarme — el puñado de arreglos detrás de la mayoría de las aceleraciones reales?»

> La mayoría de las aceleraciones son unos pocos clásicos: un mejor algoritmo, menos viajes de ida y vuelta (acaba con el N+1), cachear resultados costosos y, simplemente, hacer menos trabajo. El trabajo más rápido es el que te saltas.

## 5. El promedio y la cola

La forma de medir el rendimiento puede mentirte. El promedio es el número más tranquilizador y más engañoso, y aprender a mirar más allá de él es lo que separa el trabajo de rendimiento de verdad del pensamiento ilusorio.

### Average — el promedio esconde los casos lentos

> Una sala con nueve personas cómodas y una en llamas tiene una temperatura media agradable — la media borra el caso que de verdad importa.

Reportar el rendimiento como un **promedio** (la **media**) es peligrosamente tranquilizador: mezcla a la mayoría rápida con unos pocos lentos en un único número feliz. Pero los usuarios no viven el promedio — cada usuario vive _su_ petición, y los lentos sienten cada milisegundo.

Un tiempo de respuesta medio de 200 ms puede esconder que uno de cada veinte usuarios espera cinco segundos. La media te dice que el sistema va bien mientras una parte real de tus usuarios sufre.

_Diagram: Diecinueve peticiones rápidas y una que tarda 5 segundos — y la línea del promedio sigue pareciendo tranquila._

#### Average (Mean) (la trampa del promedio)

- **Qué es:** La suma de los tiempos dividida por el número de peticiones.
- **Cómo funciona:** Mezcla peticiones rápidas y lentas en un único número.
- **Ejemplo:** «El promedio es 200 ms» — mientras una de cada veinte peticiones espera 5 segundos.
- **Trampa:** Parece respetable mientras algunos usuarios sufren. Nunca fijes objetivos sobre él.
- **Relaciones:** Lo sustituyen los **Percentiles**; esconde la **Tail Latency**.

### Percentiles — p50 y p99 muestran la experiencia real

> Un informe que no dice solo la espera típica sino «el 1% más lento de la gente esperó esto» — nombra las malas experiencias en lugar de diluirlas en un promedio.

Los **percentiles** capturan lo que el promedio esconde. **p50** (la mediana) es el caso típico — la mitad son más rápidos. **p99** es la cola lenta — el 99% son más rápidos, así que es más o menos la peor experiencia que se encuentra un usuario real.

Vigilar el p99, y no solo el promedio, es como ves a los usuarios que de verdad están sufriendo. La cola es donde vive el dolor, y los percentiles son la forma de hacerla visible.

_Diagram: Una distribución de tiempos de respuesta: p50 está en la multitud de los rápidos, p99 muy lejos, en la cola lenta._

#### Percentiles (p50 / p95 / p99)

- **Qué es:** pN es el tiempo que el N% de las peticiones mejora. p50 es la mediana, p99 la cola.
- **Cómo funciona:** Ordena los tiempos de respuesta y toma el valor de la posición adecuada.
- **Ejemplo:** p50 = 120 ms (típico), p99 = 2 s (una de cada cien peticiones espera dos segundos).
- **Trampa:** No puedes promediar percentiles entre servidores — calcúlalos sobre todas las peticiones a la vez.
- **Relaciones:** Hacen visible la **Tail Latency**; el **Performance Target** se fija sobre ellos.

### Tail Latency — lo que los usuarios recuerdan

> Una comida terrible en un restaurante pesa más en la memoria de alguien que una docena de comidas correctas — las peores experiencias, no el promedio, moldean cómo te juzga la gente.

Las peticiones lentas — la **tail latency** — moldean de forma desproporcionada cómo perciben los usuarios tu producto, porque una mala experiencia se queda grabada.

Y a escala, la cola afecta a más gente de lo que parece: si cada página hace muchas llamadas, la probabilidad de que _al menos una_ sea lenta crece muy rápido, así que casi todos los usuarios acaban sintiendo la cola. Por eso los equipos serios fijan objetivos sobre el p99, no sobre promedios: domar los peores casos es lo que hace que un producto se sienta rápido de forma fiable.

_Diagram: Una página espera a la más lenta de sus llamadas. Con 100 llamadas y un 1% de ellas lentas, cerca del 63% de las páginas dan con la cola._

#### Tail Latency (la cola lenta)

- **Qué es:** El tiempo de las peticiones más lentas — p99 y más allá.
- **Cómo funciona:** Cuando una respuesta se ensambla a partir de muchas llamadas, espera a la más lenta de ellas.
- **Ejemplo:** Cada llamada es lenta solo el 1% de las veces, y aun así una página de 100 llamadas da con la cola cerca del 63% de las veces.
- **Trampa:** Cuantas más llamadas por respuesta, más se vuelve la norma una cola «rara».
- **Relaciones:** Se ve a través de los **Percentiles**; la esconde el **Average**.

> **La pregunta de la medición:** «¿Estoy mirando el promedio y quedándome tranquilo — o el p99, donde aparecen los usuarios que de verdad están sufriendo?»

> Los promedios esconden los casos lentos que los usuarios sienten de verdad. Vigila los percentiles — p50 para lo típico, p99 para la cola dolorosa — porque las peores experiencias son lo que la gente recuerda.

## 6. Optimización prematura

Hay un modo de fallar opuesto a ignorar el rendimiento: perseguirlo demasiado pronto, en todas partes, antes de saber si importa. La famosa advertencia al respecto es famosa por algo.

### Premature Optimization — la raíz de todos los males

> Reforzar todas las paredes de una casa contra un terremoto que quizá nunca llegue, antes de que nadie se haya mudado — un esfuerzo enorme gastado en un problema que aún no tienes.

La famosa frase de Donald Knuth — «**la optimización prematura es la raíz de todos los males**» — advierte contra optimizar antes de saber qué necesita hacerlo, o si algo lo necesita.

Optimizar código que no es lento, o que ni siquiera se ejecuta mucho, no compra nada y cuesta bastante: complejidad, errores y tiempo robado a lo que importa. La mayor parte del código no necesita ser rápido; necesita ser correcto y claro. El trabajo de velocidad es para las partes que la medición demuestra que son **calientes (hot)**.

_Diagram: De doce módulos, uno es caliente — ese es el que hay que acelerar. El resto se queda correcto y claro._

#### Premature Optimization (optimizar una corazonada)

- **Qué es:** Optimizar antes de que la medición haya demostrado que hace falta.
- **Cómo funciona:** Pagas con claridad y tiempo por velocidad en un sitio donde nadie la necesita.
- **Ejemplo:** Una semana en una caché ingeniosa para una página de ajustes que se abre una vez al mes.
- **Trampa:** El código «rápido» enredado estorba cuando el verdadero bottleneck aparece en otro sitio.
- **Relaciones:** Se cura con **Profiling**; lo explica la **Amdahl's Law**; no confundir con **Performance by Design**.

### Correct → Clear → Fast — primero correcto y claro, rápido donde cuenta

> Escribes la receta para que cualquiera pueda seguirla, y solo agilizas el único paso que haces cien veces al día — no todos los pasos, solo el caliente.

El orden es: hazlo **correcto**, hazlo **claro**, y hazlo **rápido solo donde la medición muestra que importa**.

El código claro es más fácil de optimizar más tarde precisamente porque puedes entenderlo; el código «rápido» enredado es difícil de arreglar cuando el verdadero bottleneck aparece en otro sitio. Optimizar la velocidad casi siempre cuesta legibilidad, así que gastas ese coste solo donde compra una ganancia real y medida — y mantienes simple todo lo demás.

_Diagram: El orden de los pasos: primero correcto, luego claro, y solo después rápido — y solo donde se ha medido._

#### Correct → Clear → Fast (hazlo funcionar, hazlo bien, hazlo rápido)

- **Qué es:** Un orden de prioridades: corrección, claridad y solo después velocidad.
- **Cómo funciona:** La velocidad se añade de forma quirúrgica en los puntos calientes, cuando ya existe código claro y se ha medido.
- **Ejemplo:** Escribe un handler simple y legible; el profile muestra un bucle caliente — optimiza solo ese.
- **Trampa:** Optimizar casi siempre cuesta legibilidad — gástala solo en una ganancia real.
- **Relaciones:** El antídoto contra la **Premature Optimization**.

### Performance by Design — pero no ignores el rendimiento en el diseño

> No se hace un cobertizo a prueba de terremotos, pero tampoco se construye un rascacielos sobre arena — algunas decisiones son baratas de acertar al principio y ruinosas de arreglar al final.

La advertencia no es «nunca pienses en el rendimiento». Elegir un algoritmo **O(n²)** donde uno **O(n)** era igual de fácil, o una estructura que no escalará, es un error de diseño que pagarás caro después.

El equilibrio: no hagas microoptimizaciones pronto, pero tampoco tomes decisiones de arquitectura que sean lentas por diseño y caras de deshacer. Acierta barato la **forma general** desde el principio; optimiza los **detalles** solo cuando la medición lo exija.

_Diagram: Izquierda — decisiones tomadas desde el principio: algoritmo, estructura de datos, forma de la arquitectura. Derecha — lo que se ajusta después, según el profile._

#### Performance by Design (la forma general, desde el principio)

- **Qué es:** Tomar las grandes decisiones sobre la forma de un sistema pensando en la velocidad desde el inicio.
- **Cómo funciona:** Algoritmo, estructura de datos y arquitectura se eligen pronto; el ajuste fino llega después, por medición.
- **Ejemplo:** Elegir una búsqueda indexada en lugar de recorrer toda la tabla desde el primer día — eso no es prematuro.
- **Trampa:** Es fácil esconder tras este principio la optimización prematura corriente de detalles.
- **Relaciones:** El límite de la **Premature Optimization**; su herramienta principal es **Better Algorithm**.

> **La pregunta de la contención:** «¿Estoy optimizando esto porque la medición mostró que es un bottleneck real — o solo porque puedo, cambiando claridad por una velocidad que nadie necesita?»

> La optimización prematura cambia claridad por una velocidad que nadie necesita. Hazlo correcto y claro primero, rápido solo donde la medición demuestre que importa — pero no elijas una forma lenta por diseño de la que te arrepentirás.

## 7. Usarlo bien

El rendimiento bien hecho es un método tranquilo y repetible, no una carrera heroica. Toda la práctica cabe en un bucle corto que ejecutas solo cuando hay una razón real.

### Optimization Loop — mide, arregla el bottleneck, repite

> Un mecánico diagnostica con instrumentos, arregla la única pieza que falla y vuelve a probar — nunca cambia piezas al azar esperando que el ruido desaparezca.

El método es simple y disciplinado: **mide** para encontrar el bottleneck, **arregla** esa única cosa, **vuelve a medir** para confirmar y para revelar el siguiente bottleneck, y **para** cuando sea lo bastante rápido.

Cada pasada apunta al coste dominante actual e ignora todo lo demás. Este bucle mantiene el trabajo de rendimiento honesto y eficiente — siempre sabes que trabajas en lo que de verdad importa, y siempre sabes si ayudaste.

_Diagram: Mide → encuentra el bottleneck → arregla ese → vuelve a medir. Objetivo alcanzado — para; todavía no — otra ronda._

#### Optimization Loop (el bucle de rendimiento)

- **Qué es:** Un ciclo que se repite: medir, encontrar, arreglar una cosa, comprobar.
- **Cómo funciona:** Cada ronda es un **Measure–Fix–Measure** contra el **Limiting Step** actual.
- **Ejemplo:** Ronda 1: un índice para la consulta. Ronda 2: ahora el renderizado es el bottleneck — cachea la plantilla. Objetivo alcanzado — para.
- **Trampa:** Sin un objetivo, el bucle nunca termina.
- **Relaciones:** Une **Profiling**, **Bottleneck** y **Performance Target**.

### Performance Target — fija un objetivo y para

> Aíslas la casa hasta que está lo bastante caliente y paras — no sigues añadiendo aislante para siempre, más allá del punto en que alguien lo note.

El rendimiento no tiene un final natural — siempre puedes hacer algo un poco más rápido. Así que fija un **performance target** («páginas por debajo de 300 ms en p99») y para cuando lo alcances.

Sin una meta, la optimización se convierte en un pozo de tiempo interminable con rendimientos decrecientes, y se cuela complejidad por ganancias que nadie nota. Saber qué significa «lo bastante rápido» — para tus usuarios, para tu caso de uso — es lo que te permite hacer exactamente el trabajo de rendimiento justo y luego ir a construir otra cosa.

_Diagram: El p99 baja con cada ronda. Cuando la curva queda por debajo del objetivo — para; más allá solo hay rendimientos decrecientes._

#### Performance Target (presupuesto de rendimiento)

- **Qué es:** Un número concreto de «lo bastante rápido», atado a un percentil.
- **Cómo funciona:** El bucle de optimización corre mientras la métrica esté por encima del objetivo y se detiene cuando queda por debajo.
- **Ejemplo:** «p99 de la página de inicio por debajo de 300 ms.»
- **Trampa:** Un objetivo sobre el promedio te engañará — fíjalo sobre el p99.
- **Relaciones:** La salida del **Optimization Loop**; se mide con **Percentiles**.

### Cómo encaja todo

> Toda la ruta en un solo mapa: dónde empiezas, por qué estaciones pasas y dónde te bajas.

Los conceptos forman una sola imagen. El **Profiling** encuentra el **bottleneck**; la meta — **latency** o **throughput** — te dice qué arreglar. El bottleneck suele curarse con uno de cuatro clásicos: un **mejor algoritmo**, **menos viajes de ida y vuelta**, una **caché** o **hacer menos**. Luego vuelves a medir, por **percentiles**, contra un **objetivo**, y paras. Y la **optimización prematura** es lo que pasa cuando te saltas la medición.

_Diagram: Profile → bottleneck → uno de los arreglos clásicos → mide de nuevo → un objetivo de p99 detiene el bucle. Abajo — lo que pasa sin medición._

#### Antes de optimizar

- **¿He medido** adónde se va realmente el tiempo, o estoy adivinando?
- **¿Latency o throughput** — qué tipo de rápido necesito en realidad?
- **¿Cuál es el bottleneck** — la única parte que domina el tiempo?
- **¿Es un clásico** — mal algoritmo, demasiados viajes de ida y vuelta, falta de caché, trabajo innecesario?
- **¿Estoy vigilando el p99**, y no solo el promedio que esconde la cola lenta?
- **¿Hay un objetivo** hacia el que optimizo, para saber cuándo parar?

#### Señales de que optimizas bien

- **Mides antes** de tocar nada, y **vuelves a medir** después.
- Arreglas el **bottleneck** e ignoras las partes que ya son lo bastante rápidas.
- Tus victorias vienen de **algoritmos, menos viajes de ida y vuelta y caching** — no de microajustes.
- Juzgas la velocidad por el **p99**, no por un promedio halagador.
- Optimizas hacia un **objetivo** y paras, manteniendo el resto **claro y correcto**.

## Chuleta: los 20 conceptos

### Medir

- **Profiling** (profiler): Mide dónde gasta realmente el tiempo un programa, función por función.
- **Measure–Fix–Measure** (vuelve a medir): Cada arreglo es una hipótesis que confirma una segunda medición.

### Objetivos de velocidad

- **Latency** (tiempo de respuesta): El tiempo de una operación, de principio a fin — lo que siente un usuario.
- **Throughput** (peticiones por segundo): Cuánto trabajo maneja el sistema por segundo.
- **Batching** (agrupar el trabajo): Agrupa el trabajo: el throughput sube, y la latency también.

### Bottleneck

- **Bottleneck** (el coste dominante): La única parte que se lleva la mayor parte del tiempo.
- **Limiting Step** (el siguiente bottleneck): Un sistema es tan rápido como su paso más lento; arréglalo y aparece el siguiente.
- **Amdahl's Law** (limitada por la proporción): Tu ganancia está limitada por la proporción de tiempo que ocupa la parte acelerada.

### Las mayores victorias

- **Better Algorithm** (Big-O): Cambia el enfoque: O(n²) → O(n) vence a cualquier hardware.
- **N+1 Query** (viajes de ida y vuelta de más): Una consulta por cada elemento de la lista; se cura trayendo en bloque.
- **Caching** (recordar resultados): Recuerda un resultado costoso y no lo calcules de nuevo.
- **Doing Less** (evaluación perezosa): Sáltate el trabajo innecesario: de forma perezosa, solo los datos que necesitas, sin resultados que se tiran.

### La cola

- **Average (Mean)** (la trampa del promedio): Un número tranquilo que esconde los casos lentos.
- **Percentiles** (p50 / p99): p50 es el caso típico, p99 más o menos lo peor con lo que se topa un usuario real.
- **Tail Latency** (la cola lenta): Las peticiones más lentas; la gente las recuerda, y con muchas llamadas casi todos dan con ellas.

### Contención

- **Premature Optimization** (optimizar una corazonada): Acelerar cosas antes de que la medición muestre la necesidad.
- **Correct → Clear → Fast** (hazlo funcionar, bien, rápido): Primero correcto, luego claro, rápido solo en los puntos calientes.
- **Performance by Design** (la forma general): Acierta desde el principio la forma general (algoritmo, estructura, arquitectura).

### Práctica

- **Optimization Loop** (el bucle): Mide → arregla un bottleneck → mide de nuevo → repite.
- **Performance Target** (lo bastante rápido): Un número de «lo bastante rápido» en p99 — donde se detiene el bucle.

> El rendimiento es un bucle tranquilo: mide, arregla el único bottleneck, mide de nuevo, para al llegar al objetivo. Recurre a él solo donde se haya demostrado que importa, y mantén todo lo demás claro.

Fin del curso exprés · 7 capítulos · 20 conceptos

Ahora toca practicar: toma algo que se sienta lento y, en lugar de adivinar, hazle profiling de verdad — encuentra la única función o consulta que domina, arregla solo esa y mide el antes y el después. Luego mira su p99, no solo el promedio. El método se demuestra a sí mismo en el momento en que un único arreglo dirigido, encontrado por medición, hace más que una semana de corazonadas. Pero quédate con una idea por encima de las demás: mide primero. Casi todo desastre de rendimiento es alguien optimizando lo que adivinó en lugar de lo que midió — y casi toda victoria real es encontrar el único bottleneck que importaba y arreglar exactamente ese.
