Benchmarks
Mediciones nuevas, tomadas el 18 de octubre de 2026 en la máquina descrita abajo, de dos bibliotecas de caché en proceso con protocolo single-flight: gateway_cache (Go) y cpp-cache (C++20). No son las pruebas de 2023 de la arquitectura completa descritas en 100K peticiones por segundo ni tráfico de producción: miden cada biblioteca sola, con carga sintética. El procedimiento general está en Cómo medimos; el protocolo, los scripts y los datos crudos, en simylresearch/simyl-benchmarks.
En tres conclusiones
- El single-flight funciona en las dos bibliotecas. En el arranque en frío, 64 trabajadores pidiendo 100 claves sin calcular produjeron exactamente 100 llamadas al backend en ambas: nadie recomputa lo que otro ya está calculando.
- En el camino de acierto,
cpp-cacherinde más y gasta menos memoria. Con un trabajador atiende unos 3,7 millones de peticiones por segundo frente a 1,8 millones degateway_cache; de 4 a 16 trabajadores las dos se estabilizan en torno a 1,6–2,1 millones, con un p99 más bajo y entre un tercio y la mitad de la memoria encpp-cache. - Cuando manda el backend, la biblioteca deja de importar. Con fallos frecuentes y un backend de 1 o 2 ms, las dos quedan entre unas 19.000 y 24.000 peticiones por segundo: el rendimiento lo fija el backend, y una caché en proceso no lo cambia.
Lo que estas cifras no muestran está en «Lo que muestran y lo que no», más abajo: ni red, ni serialización, ni otro hardware.
Qué se midió
| Biblioteca | Lenguaje | Fuente medida |
|---|---|---|
gateway_cache | Go | github.com/geniussportsgroup/gateway_cache/v3 v3.1.0 (MIT) |
cpp-cache | C++20 | lrleon/cpp-cache 5bfaf38 + lrleon/Aleph-w d37658b (MIT), descargados por hash |
- Una traza de 4.000.000 de peticiones por escenario, generada con semilla fija y distribución Zipf, que las dos bibliotecas reproducen idéntica.
- W trabajadores recorren la traza desde posiciones distintas; cada petición llama a la operación «obtener o calcular» con la clave como cadena.
- El backend simulado cuenta sus llamadas y duerme la latencia del escenario; se publica el tiempo real que durmió («backend real»).
- Latencia por petición en un histograma log-lineal (resolución ≈ 6 %); rendimiento = peticiones completadas por segundo entre todos los trabajadores.
- Calentamiento sin medir, 10 s medidos (3 s en el arranque en frío), 3 repeticiones alternando bibliotecas. Cada celda es la mediana; el rango mín.–máx. del rendimiento muestra la variabilidad. Los percentiles p99,9 y el máximo de cada corrida están en el
RESULTS.mddel repositorio.
Dónde y cuándo
- Máquina: AMD Ryzen 7 PRO 7840U w/ Radeon 780M Graphics (8 núcleos, 16 hilos, L3 16 MiB); 58,5 GiB de memoria; Ubuntu 24.04.5 LTS, kernel 6.8.0-146-generic. Portátil con perfil de energía «balanced» y gobernador
powersave(amd-pstate-epp), conectado a la corriente. - Herramientas: Go 1.24.4; GCC 13.2.0; CMake 3.28.3. Harness en el commit
2614b33. - Fecha: 18 de octubre de 2026. Duración total del protocolo: 501 s; 42 corridas (14 configuraciones por 3 repeticiones), con 0 errores en los datos crudos.
- Es un portátil en uso normal, no un servidor aislado: la variabilidad entre repeticiones se publica como rango. Las cifras no se extrapolan a otro hardware ni a tráfico real.
Resultados
Aciertos: rendimiento según trabajadores
100.000 claves que caben en la caché, backend sin costo, TTL de 60 s y calentamiento de 4 s para recorrer toda la traza: el camino de acierto y la contención del cerrojo de 1 a 16 trabajadores.
| Biblioteca | Trabajadores | Peticiones/s (mediana) | Mín.–máx. | p50 µs | p99 µs | Llamadas al backend | Backend real µs | RSS MB |
|---|---|---|---|---|---|---|---|---|
cpp-cache | 1 | 3.729.630 | 3.525.642–3.767.226 | 0,1 | 0,9 | 0 | 0 | 51,4 |
gateway_cache | 1 | 1.825.178 | 1.808.629–1.933.327 | 0,4 | 1,9 | 0 | 0 | 122 |
cpp-cache | 4 | 2.074.345 | 1.846.801–2.149.483 | 0,6 | 13,8 | 0 | 0 | 51,5 |
gateway_cache | 4 | 1.628.152 | 1.530.965–1.696.679 | 0,5 | 65,5 | 0 | 0 | 138 |
cpp-cache | 8 | 2.145.859 | 1.827.492–2.265.028 | 1,8 | 21,5 | 0 | 0 | 51,6 |
gateway_cache | 8 | 1.673.045 | 1.594.018–1.677.353 | 0,5 | 139 | 0 | 0 | 140 |
cpp-cache | 16 | 1.907.896 | 1.786.557–2.120.210 | 3,6 | 53,2 | 0 | 0 | 51,7 |
gateway_cache | 16 | 1.673.797 | 1.540.942–1.682.224 | 0,4 | 279 | 0 | 0 | 154 |
Fallos con desalojo LRU
1.000.000 de claves, Zipf 0,8, capacidad 10.000, backend de 1 ms, 16 trabajadores: tráfico dominado por fallos con desalojo LRU constante. Las llamadas al backend frente a los fallos muestran cuántos fallos concurrentes sobre la misma clave se agruparon.
| Biblioteca | Trabajadores | Peticiones/s (mediana) | Mín.–máx. | p50 µs | p99 µs | Llamadas al backend | Backend real µs | RSS MB |
|---|---|---|---|---|---|---|---|---|
cpp-cache | 16 | 19.616 | 19.616–19.623 | 1.049 | 1.049 | 150.875 | 1.058 | 24,0 |
gateway_cache | 16 | 18.811 | 18.706–18.838 | 1.049 | 1.180 | 144.582 | 1.101 | 52,3 |
Arranque en frío con 64 trabajadores
100 claves, distribución uniforme, 64 trabajadores, backend de 50 ms, sin calentamiento: todos piden claves que nadie ha calculado. Con single-flight el backend se llama exactamente 100 veces; sin él, hasta 64 veces por clave.
| Biblioteca | Trabajadores | Peticiones/s (mediana) | Mín.–máx. | p50 µs | p99 µs | Llamadas al backend | Backend real µs | RSS MB |
|---|---|---|---|---|---|---|---|---|
cpp-cache | 64 | 3.011.286 | 2.888.972–3.043.999 | 2,9 | 188 | 100 | 50.060 | 21,5 |
gateway_cache | 64 | 2.548.668 | 2.538.227–2.597.707 | 0,3 | 410 | 100 | 50.302 | 69,8 |
Claves calientes y frías con TTL de 1 s
200.000 claves, Zipf 1,0, backend de 2 ms, TTL de 1 s, 16 trabajadores: las dos bibliotecas renuevan el TTL en cada acierto, así que las claves populares no caducan y las pedidas menos de una vez por segundo se recomputan. Mezcla de aciertos de microsegundos y recomputaciones de 2 ms.
| Biblioteca | Trabajadores | Peticiones/s (mediana) | Mín.–máx. | p50 µs | p99 µs | Llamadas al backend | Backend real µs | RSS MB |
|---|---|---|---|---|---|---|---|---|
cpp-cache | 16 | 24.060 | 24.041–24.097 | 0,9 | 2.032 | 77.415 | 2.061 | 42,2 |
gateway_cache | 16 | 21.866 | 21.770–21.867 | 2,7 | 2.228 | 71.842 | 2.208 | 71,8 |
Lo que muestran y lo que no
- El single-flight funciona en las dos bibliotecas. En el arranque en frío, 64 trabajadores pidiendo 100 claves sin calcular produjeron exactamente 100 llamadas al backend en ambas; la latencia máxima (≈ 51 ms) es la espera de una sola llamada de 50 ms.
- Camino de acierto. Con un trabajador,
cpp-cacheatiende unos 3,7 millones de peticiones por segundo ygateway_cacheunos 1,8 millones. De 4 a 16 trabajadores las dos se estabilizan (≈ 1,9–2,1 millones y ≈ 1,6–1,7 millones): el cerrojo global de cada una limita la escalabilidad. Bajo contención la mediana decpp-cachesube a 3,6 µs mientras la degateway_cachese queda en 0,4 µs, pero el p99 decpp-cachecon 16 trabajadores es de 53 µs frente a 279 µs. Memoria residente con 100.000 entradas: ≈ 52 MB frente a 122–154 MB. - Cuando manda el backend. Con un millón de claves, capacidad de 10.000 y un backend de 1 ms, las dos rinden ≈ 19.000 peticiones/s con 16 trabajadores: el rendimiento lo fija trabajadores ÷ (fracción de fallos × latencia del backend), no la caché. Las llamadas al backend igualan los fallos en ambas: con tantas claves distintas, dos trabajadores rara vez fallan a la vez sobre la misma clave, así que el single-flight apenas interviene.
- Claves calientes y frías. Con TTL de 1 s y backend de 2 ms, ambas quedan en ≈ 22.000–24.000 peticiones/s: las recomputaciones de las claves frías dominan y el p99 de las dos es el propio backend (≈ 2 ms).
- Variabilidad. En los escenarios de aciertos el rango entre repeticiones alcanza el 10–25 % según el caso: es un portátil en uso. En los escenarios dominados por el backend el rango es inferior al 1 %.
- Lo que no muestran. Ni capa HTTP, ni serialización, ni red, ni tráfico real; nada sobre otro hardware. Las latencias simuladas son de 1 ms o más porque
time.Sleepde Go redondea los valores menores a ≈ 1 ms. Las cifras de 2023 (100K peticiones/s de la arquitectura completa) son una medición distinta y no se comparan con estas.
Reproducir
git clone https://github.com/simylresearch/simyl-benchmarks
cd simyl-benchmarks
scripts/run.sh
Los requisitos están en el README del repositorio. Datos crudos de esta medición: results/2026-10-18-ryzen7-pro-7840u/raw/results.jsonl; entorno completo: results/2026-10-18-ryzen7-pro-7840u/environment.json.
¿Quieres una medición así de tu sistema, antes y después de un cambio? Pide la llamada exploratoria