Cómo identificar cuellos de botella de I/O en pipelines de CI/CD

Aprende a diferenciar cargas limitadas por CPU e I/O en pipelines de CI/CD, interpretar métricas de rendimiento y aplicar estrategias como cargas paralelas y almacenamiento compatible con S3 para reducir significativamente los tiempos de despliegue.

Marilia Bafutto Costa - undefined

Duplicas la CPU del runner. El deploy sigue tardando lo mismo. Agregas memoria, y nada cambia.

Ese fue exactamente el escenario que encontramos durante una optimización reciente del pipeline de deploy de Azion. La primera reacción podría haber sido seguir agregando recursos, pero antes decidimos responder una pregunta simple: ¿dónde se estaba gastando realmente el tiempo?

La respuesta cambió completamente la dirección de la optimización. En lugar de un problema de procesamiento, descubrimos que gran parte del tiempo se consumía esperando que las operaciones de I/O terminaran.

Continúa leyendo para entender cómo identificar este tipo de cuello de botella, por qué más CPU no siempre resuelve el problema y qué métricas realmente ayudan a encontrar la causa de la lentitud.


Cómo identificar si el cuello de botella es I/O

Un proceso puede ser lento porque está haciendo mucho trabajo de procesamiento, o porque está esperando que lleguen los datos. En el primer caso, más CPU ayuda. En el segundo, el procesador ya está inactivo. Agregar núcleos no acelera una cola de red.

Una de las primeras señales está en el uso de CPU durante el paso lento. Si la CPU permanece baja mientras el tiempo crece, el proceso probablemente pasa gran parte del tiempo esperando operaciones de I/O.

Herramientas como top y htop suelen ser suficientes para observar esto. Pero una CPU baja por sí sola no es un diagnóstico definitivo: lock contention, rate limiting de API y procesos esperando respuesta externa producen la misma señal.

También vale la pena mirar qué está haciendo el paso lento. Upload de artefactos, pull de dependencias y clone de repositorio son operaciones de red. Su tiempo depende del protocolo y el paralelismo, no de la CPU.

Cuando sospechas de I/O de red, aumentar el paralelismo es una prueba útil, pero el resultado debe interpretarse con cuidado. Existen dos escenarios con comportamientos opuestos:

  • Latency-bound (muchas solicitudes pequeñas, alto RTT): aumentar workers ayuda, porque superpones los tiempos de espera de cada solicitud.
  • Bandwidth-bound (link saturado): aumentar workers no ayuda. El ancho de banda ya está al límite y más solicitudes simultáneas compiten por el mismo pipe.

Si aumentar workers redujo el tiempo de forma proporcional, eso indica que el cuello de botella era latencia. Si no movió el indicador, el link probablemente ya estaba saturado.

Mide cada etapa por separado. La mayoría de las plataformas de CI tienen logs con timestamp por step. Si no, time resuelve:

time ./tu-script-de-upload.sh

El comando reporta tiempo de wall-clock y tiempo de CPU. Para trabajo de I/O, verás wall-clock alto con CPU baja, lo que confirma que el proceso estaba esperando, no computando.

¿Quieres investigar más a fondo? strace -c -p <PID> recopila estadísticas de llamadas al sistema e imprime un resumen al final, útil para identificar si read, write y sendto están dominando el tiempo. En macOS, el equivalente es dtruss, pero las versiones recientes requieren deshabilitar System Integrity Protection (SIP) para funcionar.

Qué hacer cuando confirmas que es I/O

Cambia el protocolo. S3 soporta uploads paralelos de múltiples objetos de forma simultánea, con SDK que ya implementan paralelismo y retry de forma nativa. Para pipelines con cientos de archivos pequeños, esta diferencia aparece directamente en el tiempo total de upload.

Ajusta el paralelismo. Un punto de partida razonable es entre 2x y 4x el número de cores — no porque cores e I/O tengan una relación causal, sino porque es un proxy útil cuando no hay datos mejores. Aumenta de forma gradual y observa si el tiempo sigue bajando. Cuando se detenga, habrás encontrado el techo del link.

Reduce el volumen transferido. Cache de artefactos entre deploys, transferencia incremental y compresión de assets de texto (JS, CSS, HTML) funcionan bien. La compresión no ayuda con archivos ya comprimidos, como imágenes y fuentes.

Más CPU y más memoria no van a mover el indicador si el proceso está bloqueado esperando la red.

Cómo aplicamos esto en Azion

El upload de archivos estáticos tardaba entre 1 minuto 35 segundos y 1 minuto 45 segundos. Con cientos de assets, esa etapa por sí sola retrasaba cada release. La primera hipótesis fue aumentar la CPU y la memoria del entorno de ejecución. El resultado fue cero.

Las mediciones indicaron que la etapa estaba limitada principalmente por el costo de múltiples operaciones de red secuenciales y el bajo paralelismo del proceso de upload.

La solución llegó en dos frentes: migración a Azion Object Storage vía protocolo S3, que soporta uploads paralelos de múltiples archivos de forma simultánea, y el aumento del paralelismo de la CLI de un valor fijo de 5 workers a hasta 20 simultáneos, calculados de forma dinámica con base en los cores de CPU como heurística de partida. Los dos cambios juntos redujeron el upload a entre 3,5 y 9 segundos — una reducción del 90%.

El equipo de ingeniería documentó el proceso completo, con las decisiones de arquitectura, el código de asignación dinámica de workers y los benchmarks. Lee el post completo aquí.

El impacto en el ciclo de desarrollo

Un upload lento fragmenta el flujo. Inicias el proceso, abres otra pestaña y pierdes el contexto. Con el upload cayendo de casi dos minutos a menos de diez segundos, el ciclo entre escribir código y ver el resultado en producción se vuelve lo suficientemente corto para probar, ajustar y republicar antes de perder el hilo.

En equipos que hacen deploy varias veces al día, esta diferencia se acumula en el trabajo que puedes hacer sin interrupciones.

Estas mejoras ya están en el pipeline de Azion Console. Si has desplegado a través de Azion en las últimas semanas, ya estás corriendo en el nuevo pipeline, sin ningún ajuste en tu proyecto.

CLI v4.21.0 o superior para correr con las mejoras de upload. Si todavía no usas Azion, crea tu cuenta en azion.com y haz el primer deploy hoy.


Preguntas frecuentes

¿Cómo saber si mi pipeline de CI/CD tiene un cuello de botella de I/O y no de CPU? Monitorea el uso de CPU durante el paso más lento del pipeline con top o htop. Si la CPU permanece por debajo del 30–40% mientras el tiempo de ejecución crece, el proceso probablemente está esperando operaciones de red o disco, no ejecutando trabajo de procesamiento. Para confirmar, compara el tiempo de wall-clock con el tiempo de CPU reportado por el comando time — wall-clock alto con CPU baja es la firma típica de un cuello de botella de I/O.

¿Por qué aumentar workers paralelos resuelve cuellos de botella de I/O en algunos casos pero no en otros? Depende del tipo de cuello de botella. Si el problema es latencia — muchas solicitudes pequeñas esperando respuesta individualmente — aumentar workers ayuda porque superpones los tiempos de espera, reduciendo el tiempo total. Si el problema es ancho de banda saturado, más workers no ayudan porque el link ya está al límite y las solicitudes adicionales compiten por el mismo pipe. La prueba práctica: si duplicar el número de workers reduce el tiempo de forma proporcional, el cuello de botella era latencia. Si no mueve el indicador, el límite es el ancho de banda disponible.

¿Cuál es la diferencia entre un cuello de botella de CPU, de I/O de disco y de I/O de red en pipelines de CI/CD? Un cuello de botella de CPU ocurre cuando el proceso usa activamente los núcleos disponibles — compilación pesada, transpilación, minificación. Agregar CPU o paralelismo de hilos ayuda directamente. Un cuello de botella de I/O de disco ocurre en operaciones de lectura y escritura de archivos locales — instalación de dependencias en disco lento, generación de muchos archivos pequeños. Los SSD y el cache de artefactos son las principales mitigaciones. Un cuello de botella de I/O de red es el más común en etapas de upload y download — transferencia de artefactos, pull de imágenes Docker, clone de repositorio. El tiempo depende del protocolo, el paralelismo y la latencia hasta el destino, no de los recursos del runner.

mantente actualizado

Suscríbete a nuestro boletín informativo

Recibe las últimas actualizaciones de productos, destacados de eventos y conocimientos de la industria tecnológica directamente en tu bandeja de entrada.