Gasto agrupado por categoría

Gana FxDart

Requisito

Totaliza nueve transacciones de agosto por categoría, e imprime los totales en el orden en que cada categoría aparece por primera vez en el extracto. Los datos están en el código; las dos versiones deben imprimir las líneas que aparecen bajo Salida esperada.

Salida esperada
groceries: 69
transport: 23
dining: 72

Lado a lado

RxDart

FxDart

Por qué difieren

El agrupado es donde el compromiso del modelo push con «todo es un stream» sale caro. El groupBy de RxDart no puede devolver un mapa — la fuente podría no terminar nunca — así que devuelve un stream de streams: un GroupedStream por cada clave nueva. Para sacar los totales, cada stream interno debe plegarse (un Future), el future elevarse de vuelta a stream (asStream) y los resultados mezclarse con flatMap — tres capas de fontanería alrededor de un sum. (Un usuario rx pragmático puede esquivar groupBy por completo plegando el stream entero en un mapa mutable — más corto, pero abandona el operador del que trata este ejemplo y el agrupado vuelve a ser imperativo.) Y la forma tiene aristas afiladas: pliega con asyncExpand en lugar de flatMap y el programa entra en deadlock, porque pausar el stream exterior mientras se espera el total de un grupo detiene la fuente que debe completarse antes de que ningún grupo pueda cerrarse.

Los datos de FxDart son finitos por construcción, así que agrupar no necesita streams-de-streams: groupedBy produce records (key, items) corrientes en orden de primera aparición de la clave y la cadena sigue adelante, con sumBy haciendo la aritmética por grupo. Nada se aplaza porque nada sigue llegando. Para feeds vivos e ilimitados el diseño de GroupedStream es la decisión correcta — pero para un extracto que ya está en la mano, este es un trabajo con forma de pull y la versión pull lo dice en tres líneas. El veredicto se lo lleva FxDart.

Benchmark

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

N = 100

Tiempo Empate

RxDart 24 µs
FxDart 4.9 µs

Memoria pico Empate

RxDart 16.7 MB
FxDart 16.4 MB

N = 1,000,000

Tiempo Gana FxDart

RxDart 104.8 ms
FxDart 44.6 ms

Memoria pico Empate

RxDart 92.5 MB
FxDart 96.2 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í.