Tabla de retención por cohortes

Gana FxDart

Requisito

Cada usuario (los datos están en el código) tiene un mes de alta y la lista de meses en los que estuvo activo. Agrupa a los usuarios en cohortes por mes de alta y, para cada mes posterior, imprime qué porcentaje de la cohorte seguía activo —una fila por cohorte, de la más antigua a la más reciente. Ambas versiones deben imprimir la tabla que aparece bajo Salida esperada.

Salida esperada
Cohort retention by signup month
2026-04 (4 users): 2026-05 50% | 2026-06 50% | 2026-07 25%
2026-05 (3 users): 2026-06 33% | 2026-07 67%
2026-06 (2 users): 2026-07 50%

Lado a lado

Dart nativo

FxDart

Por qué difieren

Una tabla de retención es un pipeline dentro de otro pipeline: las cohortes por fuera, los meses por dentro. En FxDart ambas capas son expresiones —groupBysortBymap sobre las cohortes y, dentro de cada fila, dropWhile salta los meses hasta el mes de alta antes de que filter + size cuenten los usuarios que siguen activos. La versión nativa necesita una lista acumuladora mutable por capa (rows, cells) y dos bucles for anidados para coserlas; la lógica de retención en sí es la misma, pero está repartida por los cuerpos de los bucles en lugar de ser la columna vertebral visible del código.

Benchmark

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

N = 100

Tiempo Empate

Dart nativo 47 µs
FxDart 37 µs

Memoria pico Empate

Dart nativo 16.5 MB
FxDart 17.1 MB

N = 10,000

Tiempo Empate

Dart nativo 2.43 ms
FxDart 2.02 ms

Memoria pico Empate

Dart nativo 17.5 MB
FxDart 18.3 MB

N = 1,000,000

Tiempo Empate

Dart nativo 717.6 ms
FxDart 722.8 ms

Memoria pico Empate

Dart nativo 238.8 MB
FxDart 239.0 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í.