Gran final — cierre mensual de DailyLedger
Requisito
Cierra el mes de un libro de cuentas personal. Diez entradas viven en un almacén (datos fijos en el código de abajo); carga cada una por id —como máximo tres cargas en curso, tal como demuestra el contador de máximo en curso— y luego calcula el cierre de julio de 2026: quédate solo con las entradas de julio (una rezagada es de junio), separa los ingresos de los gastos, suma cada lado e imprime el neto junto con las tres categorías de gasto principales y su número de entradas.
Las formas que ves aquí están sacadas de una app real: el modelo
Entry, la separación ingresos/gastos (filter →
partition → sumBy en cada mitad) y el desglose
por categoría (groupBy → sumBy por grupo →
sortBy descendente → take(3)) son un calco de
los pipelines monthSummary y
categoryBreakdown de DailyLedger, con la fase de carga
asíncrona (toAsync → map →
concurrent(3)) por delante.
Salida esperada
July 2026 close — 10 entries loaded, 3 at a time (max in flight: 3) income $3600.00 expense $1478.15 net $2121.85 top spending categories: housing: $1150.00 (1 entry) food: $206.35 (3 entries) utilities: $106.30 (2 entries)
Lado a lado
Dart nativo
FxDart
Por qué difieren
Cincuenta ejemplos después, este es el patrón al que todos apuntaban:
Dart nativo necesita tres dialectos para una sola funcionalidad —los
helpers de package:collection para agrupar,
fold con valores iniciales explícitos para los totales, y
un pool de workers escrito a mano en cuanto la fase de carga necesita un
límite de concurrencia—. Cada pieza está bien por separado; juntas
convierten la lógica de negocio en lo más difícil de encontrar en la
pantalla. La versión con FxDart usa el mismo vocabulario desde la fase
de carga hasta el informe, y como cada etapa es un pipeline puro, se
puede extraer cualquiera de ellas y probarla de forma unitaria como
entran entradas, salen datos de vista.
Estos pipelines no son un adorno de demostración: son exactamente cómo la app de demostración DailyLedger calcula su panel —mismo modelo, mismos operadores, funcionando en vivo en tu navegador. Si las cincuenta comparaciones te enseñaron las palabras, DailyLedger es la frase que iban construyendo.
Benchmark
Caso async: la escala principal es N = 20,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 Empate
N = 20,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í.