Una línea por defecto para un informe vacío

Empate

Requisito

Un informe de gastos filtra las transacciones de este mes a la categoría travel — y no hay ninguna. Un informe vacío no debe quedarse sin imprimir nada: debe imprimir en su lugar una única línea de no travel spending. Los datos están en el código; las dos versiones deben imprimir la línea que aparece bajo Salida esperada.

Salida esperada
no travel spending recorded in August

Lado a lado

RxDart

FxDart

Por qué difieren

Casi en nada — y en el mismo sitio. «El vacío necesita un fallback» es un problema con el que ambos modelos chocan exactamente en el mismo lugar — una etapa aguas abajo no puede distinguir filtrado hasta quedar en nada de nunca hubo nada a menos que el pipeline diga qué emitir en ese caso — y ambas bibliotecas responden con un operador. El defaultIfEmpty de RxDart inyecta el valor por defecto cuando la fuente se completa sin ningún evento; el defaultIfEmpty de FxDart (tomado abiertamente del vocabulario Rx, con ifEmpty(() => fallback) como forma perezosa sobre el iterable completo) lo produce cuando el primer tirón no encuentra nada.

La diferencia residual es la habitual en esta Parte: la versión stream tiene que enterarse de que está vacía esperando a la terminación, así que el programa entero se vuelve asíncrono sobre una lista fija, mientras que la versión pull descubre el vacío de forma síncrona en la primera demanda. Ese coste es real pero pequeño aquí, y la paridad de operadores es la historia — un empate genuino, y un bonito ejemplo de las dos bibliotecas intercambiando ideas en lugar de competir.

Benchmark

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

N = 100

Tiempo Empate

RxDart 8.0 µs
FxDart 895 ns

Memoria pico Empate

RxDart 16.5 MB
FxDart 16.5 MB

N = 1,000,000

Tiempo Gana FxDart

RxDart 51.9 ms
FxDart 7.33 ms

Memoria pico Empate

RxDart 123.5 MB
FxDart 121.8 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í.