El resultado más rápido primero

Empate async

Requisito

Ejecuta seis consultas de usuario con tiempos de respuesta distintos, como mucho 3 a la vez, y reporta los resultados en orden de terminación — la consulta más rápida se imprime primero, sin importar dónde estaba en la entrada. Los retardos están elegidos para que el orden sea estable (usuario 2, luego 1, 4, 3, 5, 6). Los datos están en el código; las dos versiones deben imprimir las líneas que aparecen bajo Salida esperada.

Salida esperada
user#2
user#1
user#4
user#3
user#5
user#6

Lado a lado

RxDart

FxDart

Por qué difieren

Este es el reflejo especular del ejemplo anterior, y el veredicto se voltea a tablas. El orden de terminación es lo que una fusión es: el flatMap(maxConcurrent: 3) de RxDart se suscribe a tres streams internos y reenvía el que dispare primero, así que «el más rápido primero, de tres en tres» es el comportamiento literal del operador — nada que añadir, nada que deshacer.

El comportamiento por defecto de un pipeline pull es el opuesto — los resultados vuelven en el orden en que se demandaron — así que FxDart ofrece el orden de terminación como variante con nombre: concurrentPool(3) mantiene tres pulls abiertos y entrega el que se resuelva primero, exactamente como la fusión. Cada biblioteca alcanza este requisito en un operador; la única diferencia real es qué comportamiento le sale gratis a cada modelo y a cuál tuvo que ponerle nombre. Elige según el orden que necesites — mapConcurrent cuando los resultados deben alinearse con las entradas, flatMap / concurrentPool cuando la latencia hasta el primer resultado importa más.

Benchmark

Apple M1 Max, 32 GB de RAM · Dart 3.12.2 (compilado AOT) · 2026-08-18

Caso async: la escala principal es N = 10,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

RxDart 376 µs
FxDart 366 µs

Memoria pico Empate

RxDart 16.5 MB
FxDart 17.0 MB

N = 10,000

Tiempo Empate

RxDart 33.7 ms
FxDart 33.1 ms

Memoria pico Gana FxDart

RxDart 29.8 MB
FxDart 22.3 MB

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í.