Conceptos

Coordinated omission: qué es y cómo evitarla

7 min de lectura

La coordinated omission es un error de medición: un generador de carga espera cada respuesta lenta antes de enviar su siguiente petición, así que envía menos justo cuando el sistema va lento y registra muy pocos de los peores momentos. Los percentiles que lees después parecen mejores que lo que vivieron los usuarios. Se evita enviando las peticiones según una programación que ignora los tiempos de respuesta y midiendo cada petición desde el momento en que debía salir.

Los datos sobre las herramientas salen de la documentación o el repositorio de cada proyecto, comprobados el 9 de octubre de 2026.

HerramientaQué ofreceQué revisar
wrk2Una tasa constante (-R), latencia medida desde el envío previsto--u_latency añade la vista sin corregir
HdrHistogramDos métodos que rellenan las muestras que faltanAplicar solo uno, nunca los dos
k6Los ejecutores arrival-rateEl contador dropped_iterations
GatlingPasos de injectOpen como constantUsersPerSecQue los pasos estén dentro de injectOpen
Locustconstant_throughput marca el ritmo de cada usuarioLa tasa lograda frente al objetivo
JMeterOpen Model Thread Group (5.5 o posterior, experimental)Un Thread Group normal es un pool cerrado

¿Qué es la coordinated omission?

Es el error que aparece cuando el lado que mide deja de tomar muestras porque el sistema va lento, de modo que las muestras que faltan son justo las lentas. Perder muestras al azar apenas mueve un percentil; perderlas al compás de una ralentización los distorsiona todos.

El nombre viene de Gil Tene, cuyo mensaje de 2013 en una lista de correo traza esa misma línea. Es el autor original de HdrHistogram, wrk2 está en su cuenta de GitHub y la documentación de ambos proyectos explica el efecto (comprobado el 9 de octubre de 2026). La documentación de k6 usa el término para un modelo de carga cerrado que frena su propia carga, una causa frecuente. Nuestro artículo sobre el modelo de carga abierto vs cerrado trata esa elección; este se centra en la medición.

¿Cómo acaba una prueba de carga ocultando las respuestas lentas?

Un generador en bucle cerrado envía la siguiente petición por una conexión solo cuando llega la respuesta anterior. Si una respuesta tarda un segundo, esa conexión no envía nada durante un segundo, y las peticiones que habría enviado nunca obtienen un tiempo de respuesta.

El README de wrk2 lo dice del modelo de wrk, que mide cada petición desde el primer byte enviado hasta la respuesta completa: como una conexión solo envía tras una respuesta, el generador se coordina con el servidor y evita medir durante los periodos de alta latencia (comprobado el 9 de octubre de 2026).

El README de HdrHistogram plantea un experimento mental. Un sistema muestreado cada 10 ms responde en 1 ms durante 100 segundos y luego se queda parado 100 segundos, lo que deja una única muestra de 100 segundos. El histograma en bruto sitúa cerca del 99,99 % de los resultados en 1 ms o menos; corregido por las muestras bloqueadas, solo la mitad aproximadamente.

¿Cómo saber si tus resultados tienen coordinated omission?

Compara la tasa enviada con la prevista. Si la tasa de peticiones bajó mientras subían los tiempos de respuesta, el generador aflojó y el periodo lento está infrarrepresentado.

  • La carga se definió en usuarios o conexiones, sin tasa. Cualquier bucle cerrado puede provocar el error.
  • La tasa de peticiones cae donde suben los tiempos de respuesta. Un bache en la tasa durante un pico significa que hubo peticiones que nunca salieron.
  • El máximo es muchísimo mayor que el percentil 99. Unas pocas muestras enormes entre miles de rápidas son el ejemplo anterior en miniatura. Lee toda la distribución de tiempos de respuesta, sabiendo que solo cuenta las peticiones enviadas.
  • Al generador de carga le faltó CPU. LoadFocus documenta que un motor cerca del 100 % de CPU no puede enviar a la tasa configurada, y sus resultados muestran un aviso de saturación del generador de carga cuando algún motor alcanzó o superó el 80 % de CPU en su pico.

¿Cómo evita wrk2 la coordinated omission?

Envía a tasa constante y mide cada petición desde el momento en que el plan decía que debía salir. Una petición que sale tarde porque su conexión estaba ocupada carga con la espera.

wrk2 añade a wrk un argumento de tasa (-R, peticiones por segundo en total) y registra las latencias en un HdrHistogram. --u_latency añade al informe el histograma sin corregir, marcado como CO, como en el ejemplo del propio README:

wrk -t2 -c100 -d30s -R2000 --u_latency http://127.0.0.1:80/index.html

En el segundo ejemplo del README, una pausa del servidor de 1,4 segundos durante una prueba de 30 segundos hizo que el percentil 99 corregido fuera 200 veces el no corregido. El README también califica el proyecto de experimental y advierte que las pruebas de menos de 10 a 20 segundos pueden no ser útiles (comprobado el 9 de octubre de 2026). Nuestra comparativa de herramientas de benchmark HTTP compara wrk2 con hey, oha y otras.

¿Cómo corrige HdrHistogram las latencias registradas?

Si conoces el intervalo al que debían salir las peticiones, añade las muestras que una respuesta larga bloqueó. La corrección se aplica al registrar o después, sobre una copia.

recordValueWithExpectedInterval registra un valor y, si supera el intervalo, añade valores que bajan en pasos de ese intervalo. copyCorrectedForCoordinatedOmission devuelve una copia corregida de un histograma terminado. El JavaDoc describe los dos métodos como mutuamente excluyentes (comprobado el 9 de octubre de 2026).

// intervalo previsto: 10 ms, valores en microsegundos
Histogram h = new Histogram(3);
h.recordValueWithExpectedInterval(latencyUs, 10_000);

// o, tras la prueba, sobre un histograma en bruto:
Histogram fixed = raw.copyCorrectedForCoordinatedOmission(10_000);

La corrección vale lo que vale el intervalo que le pasas. Encaja, por tanto, con un generador que debía enviar a un ritmo constante.

¿Cómo lo resuelven k6, Gatling, Locust y JMeter?

k6, Gatling y JMeter pueden iniciar trabajo según una programación que no espera respuestas. Locust marca el ritmo de cada usuario, pero no puede lanzar usuarios extra para mantener una tasa.

k6. En los ejecutores arrival-rate, las iteraciones empiezan con independencia de la respuesta del sistema mientras haya un usuario virtual libre. Cuando no lo hay, k6 se salta la iteración y la cuenta en dropped_iterations, lo que, avanzada la prueba, puede indicar que el sistema se degrada (comprobado el 9 de octubre de 2026). Una iteración descartada no tiene tiempo de respuesta, así que lee ese contador junto a los percentiles. En LoadFocus, los escenarios de tasa de llegada de los scripts de k6 se ejecutan con un número fijo de usuarios, es decir, como modelo cerrado. Ejecuta k6 por tu cuenta cuando la tasa de llegada sea lo que quieres probar.

Gatling. Pasos como constantUsersPerSec dentro de injectOpen inician nuevos usuarios virtuales a una tasa fija, hayan terminado o no los anteriores (comprobado el 9 de octubre de 2026).

Locust. constant_throughput ajusta la espera de cada usuario para que ejecute una tarea como mucho un número dado de veces por segundo. La documentación dice que el tiempo de espera solo puede limitar la tasa y no lanza usuarios nuevos, y la referencia de la API añade que tras una tarea que se pasa de su intervalo no hay espera. Una respuesta lenta retrasa igualmente a ese usuario (comprobado el 9 de octubre de 2026).

JMeter. Un Thread Group es un pool de hilos que repiten el plan en bucle, es decir, un bucle cerrado. JMeter 5.5 añadió el Open Model Thread Group, experimental, que sigue una programación como rate(1/sec) random_arrivals(2 min) y, según las notas de versión, crea hilos según haga falta (comprobado el 9 de octubre de 2026).

¿Elimina un modelo de carga abierto la coordinated omission?

Elimina la causa principal, un generador que espera antes de enviar. Quedan dos huecos: un generador sin usuarios o CPU suficientes se queda igualmente atrás respecto a su programación, y cada usuario de un recorrido de varios pasos sigue esperando sus propias respuestas.

El primero se ve como iteraciones descartadas o como un motor saturado; en ambos casos, repite la prueba con más margen. El segundo viene con la mayoría de las pruebas HTTP: el README de wrk2 señala que enviar sin esperar solo sirve con protocolos no bloqueantes o con una petición por conexión, y por eso wrk2 corrige la medición del tiempo.

FAQ

¿Quién le puso nombre a la coordinated omission? Gil Tene, el autor original de HdrHistogram, cuyo fork wrk2 de wrk está pensado para evitarla. Su mensaje de 2013 en la lista de correo mechanical-sympathy la describe como un problema al que él llama así.

¿Es la coordinated omission lo mismo que un modelo de carga cerrado? Están relacionados. Un modelo cerrado es una causa frecuente, porque cada usuario virtual espera su respuesta antes de volver a enviar, y el README de wrk2 también encuentra el efecto en código de monitorización.

¿Hay que corregir todos los histogramas de latencia? Solo si conoces el intervalo al que estaban previstas las peticiones, porque HdrHistogram lo necesita para rellenar las muestras que faltan. Aplica a un conjunto de datos uno de sus dos métodos de corrección, nunca los dos.

Lecturas relacionadas


Las afirmaciones técnicas de este artículo no se han revisado de forma independiente.

LoadFocus team
Escrito por el equipo de LoadFocus, las personas detrás de un servicio de pruebas de carga en la nube.