Consulta concurrente de precios con fallback
Requisito
Calcula el precio de un pedido de seis líneas. Cada SKU se consulta en
el servicio de precios en vivo —con un máximo de tres
consultas en vuelo—, pero al servicio le faltan algunos SKU y
devuelve null para ellos; esas líneas recurren al precio
de catálogo que lleva el propio artículo. Imprime cada línea con su
precio en orden (señalando los fallbacks), el número de fallbacks, el
total del pedido y la concurrencia máxima observada. Todos los datos
están en el código de abajo.
La cadena de FxDart hace la consulta bajo concurrent(3) y
después un segundo map aplica el fallback con un simple
??: la política de recuperación no es más que otro paso
del pipeline, aguas abajo de la petición acotada.
Salida esperada
priced 6 items, 3 lookups at a time: SKU-100 x2 @ $8.49 SKU-205 x1 @ $24.50 (catalog fallback) SKU-317 x3 @ $3.99 SKU-408 x1 @ $119.00 SKU-512 x4 @ $2.80 (catalog fallback) SKU-620 x2 @ $14.20 fallbacks used: 2 order total: $212.05 max lookups in flight: 3
Lado a lado
Dart nativo
FxDart
Por qué difieren
El fallback en sí es fácil en ambas versiones —?? es
Dart—. Lo que le falta a Dart nativo es el paso previo: hacer las
consultas de tres en tres con los resultados en el orden de entrada
obliga a recurrir al modismo del pool de workers (cursor compartido,
huecos predimensionados, Future.wait), y la lógica del
fallback acaba enterrada dentro del cuerpo del worker, donde es más
difícil de ver y de probar. En la versión con FxDart, la consulta y la
recuperación son dos etapas separadas y visibles de una misma cadena
—concurrent(3) es dueño del límite, el map
siguiente es dueño de la política— y las líneas del resumen
(filter + size para los fallbacks,
sumBy para el total) reutilizan el mismo vocabulario que
enseña el resto del sitio.
Benchmark
Caso async: la escala principal es N = 100,000, no 1,000,000. Cada elemento cuesta una vuelta del event loop en ambos lados, así que un millón de awaits reales mediría el event loop de Dart durante minutos — no el pipeline. Los retardos son de longitud cero y se conserva el límite de concurrencia del ejemplo; lo que comparan las barras es la maquinaria del pipeline.
N = 100
Tiempo Empate
Memoria pico Empate
N = 10,000
Tiempo Empate
Memoria pico Gana FxDart
N = 100,000
Tiempo Empate
Memoria pico Empate
Las barras son medianas de iteraciones cronometradas repetidas en procesos nuevos por lado (los N pequeños se agrupan por resolución del temporizador). Dos lados a menos del 5% entre sí — o a menos de 0.6 ms, una diferencia que nadie puede percibir — cuentan como empate; las carreras relativas ajustadas se vuelven a medir hasta 5 veces. En una app, cualquier cosa por debajo de unos pocos milisegundos es invisible para el usuario, gane la barra que gane. La memoria es el RSS pico del proceso. La VM de Dart y el dataset son idénticos en ambos lados, así que la diferencia entre las dos barras es lo que retiene el pipeline en sí.