VOLVER a la lista de blogs
Learn About

Rendimiento de DecisionRules: cifras reales de latencia y throughput de nuestras pruebas de carga

Dos pruebas de carga de k6, 23,1 millones de solicitudes y cero fallas. Estas son las cifras medidas de percentiles de latencia y throughput de DecisionRules en Kubernetes, incluido el punto en que el rendimiento empieza a degradarse.

Rendimiento de DecisionRules: cifras reales de latencia y throughput de nuestras pruebas de carga hero image

La mayoría de las afirmaciones de rendimiento del mercado de motores de reglas no se pueden comprobar. «Tiempos de respuesta inferiores a un segundo». «Escala masiva». «Throughput de nivel empresarial». Nada de eso indica qué incluir en un plan de capacidad.

Este artículo hace lo contrario. A continuación se presentan los resultados medidos de dos pruebas de carga de k6 ejecutadas contra DecisionRules en Kubernetes, incluidas las condiciones de prueba, las distribuciones de percentiles y el punto exacto en que la latencia empieza a degradarse. Cada cifra se puede reproducir a partir de los informes sin procesar de k6 y se limita a la configuración que la produjo.

La versión breve: una única regla de negocio de complejidad media se resuelve en menos de 10 milisegundos de media — y se mantiene por debajo de 10 ms hasta aproximadamente 8.900 resoluciones por segundo. Llevada al throughput máximo, la misma plataforma sostiene más de 15.000 resoluciones por segundo con una latencia media de solo 13,1 milisegundos. El throughput y la latencia no implican la compensación que la mayoría espera, siempre que la implementación pueda escalar horizontalmente.


Resumen de cifras verificadas

MétricaValorCondiciones
Latencia media, una tabla de decisión 8.1 ms ~5.200 resoluciones/s, 50 clientes simultáneos
Latencia media, un árbol de decisión 8.2 ms ~5.200 resoluciones/s, 50 clientes simultáneos
Latencia media, regla de flujo de 3 tablas 12.1 ms ~5.200 resoluciones/s, 50 clientes simultáneos
Latencia media combinada, carga moderada 9.5 ms ~5.200 resoluciones/s, todos los tipos de regla
Latencia media combinada, throughput máximo 13.1 ms ~15.200 resoluciones/s, 200 clientes simultáneos
Latencia p95, throughput máximo 29.0 ms ~15.200 resoluciones/s, 200 clientes simultáneos
Throughput sostenido, escalado elástico ~15,200 resoluciones/s 200 clientes simultáneos, límite de HPA de 11 réplicas
Throughput sostenido, limitado a 5 réplicas ~9,800 resoluciones/s 200 clientes simultáneos, límite de HPA de 5 réplicas
Total de solicitudes en ambas pruebas 23,170,203 ~42 minutos de tiempo de prueba combinado
Solicitudes fallidas en ambas pruebas 0 tasa de error del 0,000%

Todas las cifras de latencia son tiempos de ida y vuelta observados por el cliente (http_req_duration en k6), e incluyen el tránsito de red hasta el ingreso y de vuelta, no solo la ejecución del servidor.

Qué probamos y cómo

Ambas pruebas usaron k6 para ejecutar la Rule Solver API mediante HTTP contra DecisionRules implementado en Kubernetes con un Horizontal Pod Autoscaler. Los generadores de carga se ejecutaron en la misma región que el clúster. La validación de respuestas estuvo activada en cada llamada: una solicitud solo cuenta como exitosa si devuelve HTTP 200 y la salida de decisión supera una comprobación de contenido. En 23,1 millones de llamadas, se aprobó el 100 % de las comprobaciones.

Cada iteración de k6 ejecutó una transacción de negocio compuesta por tres llamadas independientes a Rule Solver:


ReglaTipoComplejidad
Regla 1 Tabla de decisión, 20 filas Media
Regla 2 Árbol de decisión Media
Regla 3 Flujo: ejecuta tres tablas de decisión y luego realiza cálculos de resumen sobre sus resultados combinados Mayor

Esta combinación es deliberada. Las reglas 1 y 2 representan el caso cotidiano: una única pieza autónoma de lógica de decisión. La regla 3 representa un proceso de decisión orquestado, donde una llamada de API activa varias reglas y procesamiento posterior. Probar ambas en la misma ejecución permite separar el costo de resolver una regla del costo de orquestar un proceso.

k6 informa iteraciones por segundo y cada iteración aquí equivale a tres llamadas a Solver. Todas las cifras de throughput de este artículo se recalcularon como resoluciones por segundo.

Las cargas útiles eran realistas, pero no grandes: aproximadamente 422 bytes de JSON de entrada por llamada y 1,2 KB de salida de decisión por respuesta.

El número de usuarios virtuales se escalonó en 50 → 100 → 150 → 200, manteniendo cada nivel durante cinco minutos para que el escalador automático se estabilizara antes de tomar las mediciones. Las dos pruebas fueron idénticas en todos los aspectos salvo el límite del escalador automático: 11 réplicas en una y 5 en la otra.


Carga normal: las reglas individuales se resuelven en menos de 10 milisegundos

Con 50 clientes simultáneos —5.243 resoluciones por segundo sostenidas, lo que ya representa tráfico de producción considerable— las cifras por regla son:

ReglaMediaMedianap90p95p99
Tabla de decisión (20 filas) 8.1 ms 6.9 ms 13.0 ms 14.8 ms 18.1 ms
Árbol de decisión 8.2 ms 6.8 ms 13.4 ms 15.2 ms 18.7 ms
Flujo (3 tablas + cálculos) 12.1 ms 10.2 ms 19.4 ms 21.3 ms 25.1 ms
Combinado, todas las llamadas 9.5 ms 8.4 ms 16.2 ms 18.4 ms 22.9 ms

Una tabla de decisión o árbol de decisión de complejidad media se resuelve en aproximadamente 8 milisegundos de media, menos de 7 milisegundos en la mediana, medido del lado del cliente e incluyendo la ida y vuelta por red. Dos tercios de ese tiempo corresponden a la resolución de la regla; el resto es HTTP y tránsito de red.

La cifra por debajo de 10 milisegundos no es un efecto de baja carga. Se mantiene a medida que aumenta el throughput:


RendimientoTabla de decisión (media)Árbol de decisión (media)¿Menos de 10 ms?
5,243 resoluciones/s 8.1 ms 8.2 ms
8,908 resoluciones/s 9.6 ms 9.7 ms
12,302 resoluciones/s 10.3 ms 10.6 ms La mediana aún es inferior a 10 ms
15,215 resoluciones/s 11.1 ms 11.5 ms No: 11 ms

La latencia media de una sola regla se mantiene por debajo de 10 milisegundos hasta aproximadamente 8.900 resoluciones por segundo y la mediana se mantiene por debajo de 10 milisegundos hasta aproximadamente 12,300 solves per second. Solo con la carga más alta probada una sola regla tarda más de 11 milisegundos.

Si su carga de trabajo está dominada por tablas y árboles de decisión individuales, en lugar de orquestación de varios pasos, una respuesta media inferior a 10 milisegundos es una expectativa razonable, no el mejor caso.

El costo de la regla de flujo

La regla de flujo —tres tablas de decisión más cálculos de resumen, todo detrás de una llamada de API— promedió 12,1 ms con carga moderada y 16,6 ms con throughput máximo. Frente a una sola tabla con la misma carga, esto supone un multiplicador de 1,5×, estable en todos los niveles de simultaneidad probados.

Esa proporción es la parte interesante. El flujo realiza al menos tres veces el trabajo de resolución de reglas de una sola tabla de decisión, además de agregar los resultados, por aproximadamente una vez y media la latencia. Ejecutar esas tres tablas como tres llamadas separadas a la API de Solver costaría aproximadamente 33 milisegundos con throughput máximo: tres idas y vueltas, tres conexiones HTTP, tres tránsitos de red. Orquestarlas dentro de un flujo cuesta 16,6 ms.

Consolidar lógica de decisión de varios pasos en un flujo es aproximadamente dos veces más rápido que llamar a las reglas individualmente desde su aplicación.


Rendimiento máximo: 15.200 resoluciones por segundo

Al aumentar la simultaneidad en una implementación autorizada para escalar a 11 réplicas:


Clientes simultáneosRendimiento sostenidoMedianaMediap90p95p99
50 5,243 resoluciones/s 8.4 ms 9.5 ms 16.2 ms 18.4 ms 22.9 ms
100 8,908 resoluciones/s 9.4 ms 11.2 ms 19.4 ms 23.1 ms 29.1 ms
150 12,302 resoluciones/s 10.5 ms 12.1 ms 22.3 ms 27.2 ms 35.2 ms
200 15,215 resoluciones/s 11.9 ms 13.1 ms 24.1 ms 29.0 ms 37.9 ms

Compare la primera y la última fila. El rendimiento aumentó 2.9×. La latencia media aumentó en 3,6 milisegundos. La latencia mediana aumentó en 3,5 milisegundos.

Esto se aproxima al escalado lineal. Cada incremento de simultaneidad de 50 clientes aportó aproximadamente 3.400 resoluciones adicionales por segundo, y el costo marginal de latencia de cada paso se mantuvo por debajo de 2 ms. El sistema todavía estaba escalando cuando terminó la prueba: 15.215 resoluciones/s es la tasa más alta que medimos, no un límite que hayamos encontrado.

De forma sostenida, esa tasa representa 54,8 millones de decisiones por hora, o 1.310 millones al día. No falló ninguna solicitud entre las 12.756.996 llamadas de esta prueba.

Latencia de la transacción completa

Como cada iteración realizó las tres llamadas en secuencia, la prueba también mide la transacción de negocio completa:


RendimientoMedia de la transacciónMedianp95p99
5,243 resoluciones/s 28.6 ms 24.3 ms 47.9 ms 53.5 ms
8,908 resoluciones/s 33.7 ms 29.6 ms 62.2 ms 68.2 ms
12,302 resoluciones/s 36.6 ms 35.1 ms 76.2 ms 82.8 ms
15,215 resoluciones/s 39.4 ms 37.9 ms 82.4 ms 90.5 ms

Un proceso de decisión completo —una tabla de decisión, un árbol de decisión y un flujo de tres tablas, ejecutados secuencialmente como tres llamadas de API— se completa en 28,6 ms con carga moderada y 39,4 ms con rendimiento máximo. La latencia de la transacción sigue casi exactamente la suma de sus partes, lo que significa que la sobrecarga de emitir varias llamadas secuenciales a Solver es insignificante; el costo está en las propias reglas.


La configuración que se saturó y por qué la mostramos

La segunda prueba fue idéntica en todos los aspectos salvo uno: el límite del escalador automático se estableció en 5 réplicas en lugar de 11. Este es el resultado más ilustrativo del conjunto.


Clientes simultáneosHPA máx. 5HPA máx. 11Diferencia de rendimiento
50 5,529 resoluciones/s 5,243 resoluciones/s
100 9,115 resoluciones/s 8,908 resoluciones/s
150 9,540 resoluciones/s 12,302 resoluciones/s - 23%
200 9,794 resoluciones/s 15,215 resoluciones/s - 36%

Y la latencia correspondiente:

Clientes simultáneosMedia (máx. 5)Media (máx. 11)p95 (máx. 5)p95 (máx. 11)
50 9.0 ms 9.5 ms 15.1 ms 18.4 ms
100 10.9 ms 11.2 ms 22.2 ms 23.1 ms
150 15.7 ms 12.1 ms 27.9 ms 27.2 ms
200 20.3 ms 13.1 ms 35.4 ms 29.0 ms

Hasta 100 clientes simultáneos, las dos configuraciones son indistinguibles; la implementación limitada es incluso marginalmente más rápida, porque cinco réplicas eran suficientes y la distribución de solicitudes era más ajustada. A partir de ese punto, divergen notablemente. La implementación limitada alcanza su techo en aproximadamente 9.800 resoluciones/s y deja de ganar rendimiento; la carga adicional se convierte en colas y la latencia media se duplica con creces, de 9,0 ms a 20,3 ms. La latencia de una sola regla se degrada en la misma medida, de 7,6 ms a 17,4 ms.

Vale la pena decirlo claramente: la implementación limitada no falló. Cero errores en 10,4 millones de solicitudes, p99 aún por debajo de 47 ms y se siguieron cumpliendo todos los umbrales de latencia configurados. Simplemente dejó de ser más rápida.

Un motor de reglas que se degrada con elegancia bajo saturación es posiblemente más valioso que uno que es rápido hasta que deja de serlo. Pero la lección de implementación es directa: si su carga máxima supera lo que puede absorber el límite de réplicas, eleve ese límite. El motor escala; la restricción aquí era la configuración del escalador automático, no el software.


Cómo usar estas cifras

Si está dimensionando una implementación. La prueba saturada da la cifra más clara por réplica: cinco réplicas se estabilizaron en aproximadamente 9.800 resoluciones/s, es decir, cerca de 1.950 resoluciones/s por réplica en saturación. Para tener margen, calcule ~1.400 resoluciones/s por réplica y establezca el máximo de su HPA por encima del número resultante, no exactamente en él. (El recuento de pods no se registró en la salida de k6, por lo que estas cifras se derivan de los límites del escalador automático y no de recuentos de réplicas observados.)

Si tiene un SLA de latencia. Para una sola tabla o árbol de decisión de complejidad media con carga normal, prevea 20 ms en p99, medidos del lado del cliente en la misma región. Para un flujo que orquesta varias tablas, prevea 25–41 ms en p99 según la carga. Para una transacción de negocio de tres llamadas, prevea 90 ms en p99 con el rendimiento máximo.

Si está diseñando lógica de decisión. Consolide. Tres reglas llamadas individualmente cuestan aproximadamente el doble que esas mismas tres reglas orquestadas dentro de un flujo, porque se paga la ida y vuelta por red una vez en lugar de tres.

Si está comparando motores. Compare distribuciones de percentiles, no medias. Es fácil lograr una buena media siendo rápido en el camino ideal. La diferencia entre p50 y p99 indica si el sistema forma colas, y las colas son lo que rompe los sistemas en producción.


Alcance y limitaciones

Estos resultados describen las configuraciones probadas y no deben generalizarse más allá de ellas:

  • La complejidad de la regla influye en la latencia más que cualquier otro factor. Estas pruebas usaron una tabla de decisión de 20 filas, un árbol de decisión y un flujo de tres tablas, todos de complejidad media. Una tabla de decisión de 10.000 filas, flujos de trabajo profundamente anidados o reglas con mucho scripting producirán cifras diferentes.
  • El tamaño de la carga útil importa. Estas pruebas usaron solicitudes de ~422 bytes y respuestas de ~1,2 KB. Las cargas útiles considerablemente mayores modificarán tanto la latencia como el rendimiento.
  • La topología de red queda excluida. Los generadores de carga se ejecutaron en la misma región. Las llamadas entre regiones o continentes añaden tiempo de tránsito que no tiene relación con el motor.
  • Estas no son cifras máximas alcanzables. La prueba elástica aún escalaba linealmente cuando terminó. Informamos lo que medimos, no lo que extrapolamos.
  • Las cifras de rendimiento se recalculan, no se toman de la visualización del panel de k6, por el motivo explicado en la sección «Qué probamos y cómo» anterior.

Pruebas realizadas con k6 contra DecisionRules en Kubernetes con escalado horizontal automático de pods. La latencia se midió como tiempo de ida y vuelta HTTP observado por el cliente (http_req_duration). El rendimiento se recalculó a partir de los recuentos brutos por intervalo. Informes brutos de k6 disponibles bajo solicitud.

La conclusión

Cada cifra de este artículo proviene de un informe de k6 que puede reproducir, con las condiciones indicadas, los percentiles publicados en lugar de ocultarlos en promedios y la prueba que se saturó mostrada junto a la que no se saturó. Esa última parte es clave. Un benchmark que solo muestra la configuración en la que todo salió bien no dice nada sobre lo que ocurre cuando no es así.

Si está evaluando un motor de reglas, pida lo mismo. Si no están disponibles las distribuciones de percentiles y las condiciones indicadas, lo que le muestran no es una medición.

Para probar DecisionRules con sus propias reglas y cargas útiles, solicite una demostración o inicie una prueba gratuita.

Ondrej Brejla

Ondrej Brejla

Analista de negocios