Benchmarks
Cómo se comporta la pasarela Wäg frente a LiteLLM en condiciones idénticas. Esta página expone el método completo y publica las mediciones que produjo. No publicamos multiplicadores.
Cómo se midió
Todo se ejecutó en Docker en una sola máquina, con cada componente fijado a sus propios núcleos para que nada compitiera por la CPU.
- Ambas pasarelas se sitúan ante el mismo upstream con idéntica configuración de modelo, así que ninguna tiene el camino más fácil.
- Cada pasarela se ejecuta como recomienda su propia documentación: LiteLLM según su guía de producción, con tantos workers como vCPU; Wäg con sus valores por defecto. La caché de respuestas está desactivada en ambas.
- Las pruebas en bucle cerrado miden el rendimiento máximo. Las de bucle abierto envían a un ritmo fijo y cuentan la latencia desde el instante de envío previsto, así que una pasarela que encola no puede ocultarlo.
- Cada respuesta se valida: estado, estructura del cuerpo y, en los flujos, el número de fragmentos esperado y su cierre. Todo lo demás cuenta como error, nunca como respuesta rápida.
- Cada escenario se ejecuta tres veces y las tablas muestran la mediana. Sin pasarela en el camino, la misma carga alcanza unas 90.000 req/s, muy por encima de ambas pasarelas: los resultados los limita la pasarela, no el arnés.
Huella
Lo que cuesta cada pasarela antes de servir nada: memoria en reposo, tiempo de arranque, tamaño de imagen y latencia añadida a una sola petición con un upstream instantáneo.
Qué significa: La memoria decide cuántas réplicas caben en un nodo, y el tamaño de la imagen, lo rápido que es un despliegue. Con 3,8 MB residentes y una imagen de 123 MB, Wäg cabe en un sidecar y está listo antes de que expire un health check; 2,3 GB y 11 segundos son un pod alrededor del cual hay que planificar.
La latencia añadida es el p50 de la pasarela menos el p50 medido sin pasarela en el camino.
Con un upstream realista
Un modelo real responde en cientos de milisegundos, así que hay miles de peticiones en vuelo a la vez. Aquí el upstream tarda 300 ms y las peticiones llegan a ritmo fijo haga lo que haga la pasarela. A 2.000 req/s hay unas 600 peticiones en curso en cada momento.
| peticiones por segundo | Wäg p50 | Wäg p99 | Wäg Errores | Wäg CPU | LiteLLM p50 | LiteLLM p99 | LiteLLM Errores | LiteLLM CPU | × |
|---|---|---|---|---|---|---|---|---|---|
| 100 | 303 ms | 305 ms | 0,00% | 10,2% | 305 ms | 308 ms | 0,00% | 38,7% | 1,0× |
| 500 | 301 ms | 303 ms | 0,00% | 15,6% | 304 ms | 321 ms | 0,00% | 140,5% | 1,1× |
| 1000 | 301 ms | 302 ms | 0,00% | 20,2% | 317 ms | 605 ms | 0,00% | 263,7% | 2,0× |
| 2000 | 301 ms | 302 ms | 0,00% | 31,7% | 3,26 s | 28 s | 7,99% | 391,9% | 92× |
Qué significa: Esta es la forma del tráfico real: un modelo responde en cientos de milisegundos y hay miles de peticiones en vuelo. Una pasarela que encola convierte una respuesta de 300 ms en una de varios segundos, y nadie lo nota hasta el pico. Wäg se mantiene en el suelo hasta 2.000 req/s con menos de un tercio de su presupuesto de CPU. LiteLLM ya encola a 1.000 y falla el 8% de las peticiones a 2.000.
El upstream por sí solo tarda 300 ms: ese es el suelo. Todo lo que lo supere es tiempo en cola dentro de la pasarela. La columna × se lee siempre igual: más alto significa que Wäg va por delante. Es Wäg ÷ LiteLLM para el rendimiento y LiteLLM ÷ Wäg para la latencia.
Rendimiento y latencia
Bucle cerrado contra un upstream instantáneo: coste puro de la pasarela, sin latencia de modelo tras la que esconderse. Son las cifras que necesita un plan de capacidad. No son la razón para elegir un plano de control.
4 vCPU, sin base de datos
| Clientes simultáneos | Wäg req/s | Wäg p99 | Wäg CPU | LiteLLM req/s | LiteLLM p99 | LiteLLM CPU | × |
|---|---|---|---|---|---|---|---|
| 1 | 6232 | 0,27 ms | 63,4% | 463 | 3,2 ms | 98,1% | 13× |
| 8 | 25.711 | 0,70 ms | 311,5% | 1237 | 15 ms | 286,1% | 21× |
| 32 | 25.093 | 2,6 ms | 321,8% | 1621 | 46 ms | 385,1% | 15× |
| 128 | 23.639 | 11 ms | 328,3% | 1669 | 111 ms | 396,2% | 14× |
| 512 | 22.407 | 45 ms | 336,9% | 1569 | 749 ms | 391,6% | 14× |
1 vCPU, sin base de datos
| Clientes simultáneos | Wäg req/s | Wäg p99 | LiteLLM req/s | LiteLLM p99 | × |
|---|---|---|---|---|---|
| 1 | 6589 | 0,35 ms | 459 | 3,2 ms | 14× |
| 8 | 16.594 | 1,3 ms | 484 | 26 ms | 34× |
| 32 | 15.226 | 3,8 ms | 506 | 85 ms | 30× |
| 128 | 13.264 | 15 ms | 505 | 438 ms | 26× |
Qué significa: Esto determina cuántas réplicas necesita un nivel de tráfico y, por tanto, lo que cuesta operar la pasarela. Para Kubernetes, la tabla a leer es la de 1 vCPU: es la eficiencia por núcleo que un pod obtiene realmente.
Streaming, cargas útiles, embeddings, conmutación
4 vCPU, sin base de datos. Los flujos son 50 tokens separados 5 ms; la prueba de resistencia envía 200 flujos por segundo de respuestas de unos 1,2 segundos durante tres minutos.
| Escenario | Wäg | Wäg p99 | Wäg Errores | LiteLLM | LiteLLM p99 | LiteLLM Errores | × |
|---|---|---|---|---|---|---|---|
| Streaming, 64 clients | 233 | 286 ms | 0,00% | 179 | 674 ms | 0,00% | 1,3× |
| Streaming, 256 clients | 911 | 288 ms | 0,00% | 307 | 1,09 s | 0,00% | 3,0× |
| 64 KB conversation history, 32 clients | 3583 | 29 ms | 0,00% | 568 | 106 ms | 0,00% | 6,3× |
| Embeddings (1,536 dims), 32 clients | 13.558 | 4,3 ms | 0,00% | 740 | 69 ms | 0,00% | 18× |
| Fallback after upstream 500, 16 clients | 19.816 | 1,8 ms | 0,00% | 584 | 62 ms | 0,00% | 34× |
| Soak: 200 streams/s for 3 minutes | 200 | 1,27 s | 0,00% | 176 | 20 s | 12,09% | 1,1× |
Qué significa: Streaming, prompts largos, embeddings y conmutación son los caminos donde una carga de producción pasa el tiempo. Lea las columnas de errores antes que las de rendimiento: una petición fallida es una petición de usuario fallida, no una lenta.
La cifra de cargas de 64 KB está en el techo del arnés: sin pasarela en el camino la misma carga alcanza 3711 req/s de cuerpos de 64 KB en un núcleo, así que el número de Wäg ahí es una cota inferior, no un máximo.
Lo que esto no muestra
Todo benchmark describe un montaje. Estos son los límites de este.
- Las cifras absolutas dependen del host. Ambas pasarelas se ejecutaron en la misma máquina con núcleos fijados, así que la comparación entre ellas se sostiene, pero espere valores absolutos distintos en su propio hardware.
- El arnés que condujo estas mediciones no está publicado, así que no puede repetirlas comando a comando. El método anterior se describe con detalle suficiente para reconstruir uno equivalente.
- LiteLLM publica casi cada semana. Estas cifras se midieron con v1.104.2, la versión estable actual. Cuando una versión modifique la ruta de reenvío, repetiremos la medición y publicaremos lo que salga.
- LiteLLM se configuró a partir de su guía de producción, no por sus mantenedores. Puede existir una configuración mejor; si encuentra una, repetiremos la medición y volveremos a publicar.
- Ambas pasarelas se ejecutaron en una sola máquina con núcleos fijados. Nada de esto mide el comportamiento a través de una red, bajo la planificación de Kubernetes o con vecinos ruidosos.