Un stream alimenta un pipeline tipado

Empate async

Requisito

Un feed de logs en vivo emite siete líneas con un calendario fijo y se cierra. Conserva solo los warnings, ponlos en mayúsculas para el canal de incidentes, e imprímelos con un conteo final. El feed está simulado en el código (de forma idéntica en ambos lados); las dos versiones deben imprimir las líneas que aparecen bajo Salida esperada.

Salida esperada
WARN: DISK 81% FULL
WARN: LATENCY 900MS
WARN: RETRY QUEUE AT 12
warnings: 3

Lado a lado

RxDart

FxDart

Por qué difieren

Apenas difieren — y ese es el sentido de este par. La fuente es una cosa nativa del push, un Stream que emite cuando le place, y RxDart se queda en ese modelo: mapNotNull filtra y formatea en un operador, toList recoge al cierre. Limpio, idiomático, listo.

El lado FxDart no pelea contra el stream ni re-modela la fuente — le tiende un puente. fxStream envuelve cualquier Stream como un iterable async basado en pull, y a partir de ahí el código es la misma cadena tipada que escribirías sobre una lista: filter, map, toList. El puente guarda en buffer los eventos empujados hasta que el pipeline los demanda, así que nada se pierde y el orden se conserva. Este es un ejemplo de cooperación, no de contienda: deja que el stream sea un stream en el borde donde nacen los eventos, y cruza a un pipeline pull en el momento en que quieras procesamiento tipado y dirigido por demanda — los dos modelos se componen en una línea. Empate, y deliberadamente.

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 8.9 µs
FxDart 8.8 µs

Memoria pico Empate

RxDart 16.5 MB
FxDart 16.5 MB

N = 10,000

Tiempo Empate

RxDart 762 µs
FxDart 773 µs

Memoria pico Empate

RxDart 22.9 MB
FxDart 23.5 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í.