Simulación de Eventos Discretos · Tema 45

Cuellos de botella

Dónde se concentra la congestión del sistema — el max ρ que manda el throughput y se come la espera.

01 · Punto de partida

El sistema anda al paso del más cargado

Front al 40%, app al 70%, DB al 95%: la DB manda —su Wq es el 80% del W total y su ρ decide si el sistema estabiliza. Duplicar el front no mueve nada; sumar un disco a la DB lo cambia todo. Ese max ρi es el cuello de botella.

Detectarlo (U y Lq por estación), cuantificar cuánto domina y aliviarlo en el orden correcto —porque al aliviarlo, el cuello se muda— es el trabajo de este tema.

  • ¿Cuál estación es el cuello y con qué margen sobre las demás?
  • ¿Qué fracción del W total nace en el cuello?
  • ¿Qué caminos lo alivian (+c, +μ, derivar, aceptar)?
  • ¿A dónde se muda el cuello tras aliviarlo?

02 · Definición

Detección, dominancia y alivio

◉

Detección

Ranking de ρi = λiSi/ci con Lqi al lado. Sin medición por estación no hay cuello, hay sospecha.

%

Dominancia

Wqcuello/W: fracción de la espera nacida ahí. Típico 70–90% en cuellos reales.

➚

Alivio

+c, +μ (acelerar), partir carga, derivar demanda o aceptar con K/SLA. En ese orden de costo.

Tándem λ = 0.3/min: A y C con S = 2, B con S = 3 (c = 1).
EstaciónρiWqiWi y % de W = 40
A · puerta0.603.05.0 (13%)
B · fondo0.9027.030.0 (75%) ← cuello
C · salida0.603.05.0 (13%)

03 · El corazón: medir, atacar, re-medir

El cuello se muda: iterar

ranking ρ→aliviar top-1→re-medir

Aliviar B (cB = 2) baja su ρ a 0.45 y su Wq a ~1: el cuello se muda a A/C (ρ = 0.6). Cada iteración mueve el max; el ciclo termina cuando el W total cumple SLA o el presupuesto se acaba. Es la teoría de restricciones (Goldratt) con números de colas: el throughput lo fija el cuello.

  1. 1
    Medir por estación.

    (λi, Si, ci) → ρi, Lqi, Wqi. Sin esto, el “cuello” es opinión.

  2. 2
    Rankear y cuantificar.

    argmax ρi + dominancia Wqi/W. Atacar el top-1: lo demás es decoración.

  3. 3
    Aliviar barato primero.

    Acelerar S, pooling/fila única, derivar demanda; sumar c si paga; aceptar con K/SLA si no.

  4. 4
    Re-medir (se mudó).

    El nuevo max manda: iterar hasta SLA o presupuesto. Cada vuelta abarata la siguiente decisión.

Cuello móvil
Al aliviar B, A/C pasan al frente. Quien no re-mide persigue el cuello viejo con plata nueva.
Restricción (Goldratt)
El throughput estable ≤ capacidad del cuello. Subordinar lo demás al ritmo del cuello (tambor-pulmón-cuerda).
Cuello nominal vs real
El más lento vacío no es cuello: manda ρi = λiSi/ci, tráfico por servicio.
U sin cola
U ≈ 0.9 con Lq ≈ 0 (servicio D parejo) igual es cuello: la próxima décima de λ lo desborda.

Aliviar el cuello

Mueve el total

Cada punto de ρ menos en el max baja W total y sube throughput. Inversión con retorno medible.

Aliviar otro

Mueve el cartel

Baja su ρ local sin tocar W ni throughput: el cuello sigue mandando. Típico gasto sin veredicto.

04 · Ejemplos

Cuatro cuellos con placa

  1. 1
    Web: DB al 0.95.

    Front 0.4, app 0.7: índice + réplica bajan SDB y el cuello se muda al app.

  2. 2
    Banco: informes al 0.9.

    Caja al 0.5: otra ventanilla de informes, no otra caja.

  3. 3
    Fábrica: pintura lenta.

    Corte y armado esperan: acelerar pintura o poner turno doble solo ahí.

  4. 4
    Guardia: farmacia.

    Médico atiende, farmacia entrega: la fila se muda al mostrador final.

05 · Representación en Python

Ranking y qué-si en dos bloques

ρ por estación con M/M/1 y el qué-si de sumar c al cuello: el veredicto antes de gastar.

Python en tu navegador. El primero rankea y mide dominancia; el segundo prueba +c en el cuello vs fuera. Cambiá SB.

# Ranking del tándem: lam=0.3, S=[2,3,2], c=1
lam = 0.3
ests = [("A", 2.0, 1), ("B", 3.0, 1), ("C", 2.0, 1)]
r = sorted(((n, lam*S/c) for n, S, c in ests), key=lambda x: -x[1])
print("cuello:", r[0][0], f"rho={r[0][1]:.2f}")
print([(n, round(x, 2)) for n, x in r])
# Qué-si: +c al cuello (B: rho 0.9->0.45) vs a la puerta (A)
def Wq(lam, S, c=1):
    mu = 1/S
    return lam/(mu*(mu-lam)) if lam < c*mu else float("inf")

print("B con c=2: Wq≈0.8 (Erlang C, a=0.9, rho=0.45)")
print("A con c=2: W total igual (el cuello B manda)")

06 · Exploración

Laboratorio: cazar el cuello y mudarlo

Tándem A → B → C (c = 1 salvo cB ajustable), M/M/1 por estación con SA = SC = 2. Movè λ, SB y cB: las barras ρi muestran el ranking (naranja = cuello) y las Wqi su dominancia. Poné cB = 2 y mirá la mudanza.

EXPERIMENTO 45

El max manda y se muda

cuello = argmax ρᵢ · M/M/1 por estación

Los resultados numéricos aparecen debajo.
CuelloB
ρ cuello0
W total0
% W en cuello0%

Duplicá c(B) para mudar el cuello.

Izquierda: barras ρ por estación (naranja = max). Derecha: barras Wq por estación. El % dice cuánto del W total nace en el cuello.

Preguntas para explorar

  1. Default (λ=0.3, SB=3, cB=1): ¿cuello, ρ y % de W?
  2. Poné cB=2: ¿nuevo cuello? ¿W total antes y después?
  3. Bajá SB=1: ¿quién manda? ¿Qué convino más, acelerar o duplicar?
Ver respuestas sugeridas
  1. B con ρ=0.9 y ~75% de W (30 de 40): manual del cuello.
  2. Se muda a A/C (ρ=0.6): W ≈ 40 → ~14. El alivio rinde ×3.
  3. Mandan A/C (0.6): W ≈ 40 → ~13. Similar; acelerar suele costar menos que duplicar.

07 · Comprensión

Confusiones frecuentes

«El cuello es el más lento»

Es el de mayor ρi = λiSi/ci. Un lento vacío no manda; un rápido saturado sí.

«Cualquier mejora ayuda al total»

Solo la del cuello mueve W y throughput. Mejorar otra estación baja su cartel local.

«El cuello es fijo del sistema»

Se muda con λ, S y c: cada alivio reordena el ranking. Iterar midiendo o perseguir fantasmas.

«U alta con Lq ≈ 0 no es cuello»

Sí lo es en potencia: a ρ = 0.9 con servicio parejo la fila aún no se ve, pero la próxima décima la desborda.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: ranking

ρ = [0.6, 0.9, 0.6]. ¿Cuello? ¿Dominancia si Wq = [3, 27, 3] y S = [2, 3, 2]?

Wq, S = [3.0, 27.0, 3.0], [2.0, 3.0, 2.0]
W = [q+s for q, s in zip(Wq, S)]
print(f"cuello=B W={sum(W):.0f} domina {W[1]/sum(W):.0%}")
Ver solución razonada

B: W = 40 con 75% en B. El informe cabe en una línea y decide la compra.

Ejercicio 2: mudanza

Con cB=2 (ρB=0.45, WqB≈1): ¿nuevo cuello y W?

# A/C rho 0.6 Wq 3.0; B rho 0.45 Wq ~1.0 -> W ≈ 5+4+5 = 14 (cuello A/C)
print("W 40 -> ~14: el cuello se mudó a la puerta")
Ver solución

~14 con cuello empatado A/C: la próxima plata va a la puerta, no al fondo.

Ejercicio 3: acelerar vs duplicar

SB=3→1.5 (ρ 0.9→0.45) vs cB=1→2. ¿W en cada caso?

Ver una posible respuesta
# acelerar: Wq_B ~1.0, W ≈ 5+2.5+5 = 12.5; duplicar: ~14. Parejo: gana el más barato
print("Acelerar ≈ duplicar en W: decide el precio")

Parejos en W (~13): el veredicto lo da el costo, no la cola (Tema 46).

09 · Síntesis

Ideas para recordar

  • Cuello = argmax ρi; su Wq domina W; el throughput lo limita él.
  • Medir por estación o no medir; el global esconde.
  • Aliviar top-1 (S, pooling, derivar, +c, aceptar) y re-medir: se muda.
  • En Python: ranking + qué-si antes de gastar.
  • Fuera del cuello, la mejora es cartel local.

En el próximo tema pondremos precio: el dimensionamiento de recursos.