Visitantes únicos, conservando la primera visita

Empate

Requisito

El registro de visitas de hoy contiene ocho visitas de cuatro cuentas. Conserva solo la primera visita de cada usuario — deduplicando a lo largo de todo el registro, no solo entre entradas adyacentes — e imprime quiénes son, cuándo llegaron por primera vez y el recuento de únicos. Los datos están en el código; las dos versiones deben imprimir las líneas que aparecen bajo Salida esperada.

Salida esperada
ana — first visit 09:02
ben — first visit 09:15
cho — first visit 10:05
dee — first visit 11:01
4 unique visitors in 8 visits

Lado a lado

RxDart

FxDart

Por qué difieren

Este es uno de los mejores emparejamientos de RxDart con un operador de FxDart. El Stream.distinct corriente solo compara eventos adyacentes (el uniqAdjacent de FxDart es la misma idea), así que RxDart añade distinctUnique: deduplicación a lo largo de todo el stream, conservando la primera aparición — exactamente el contrato de uniqBy. Ambos mantienen un conjunto de vistos durante la vida del stream, ambos preservan el orden de llegada, y las revisitas de ana a las 09:40 y las 11:48 desaparecen de forma idéntica en ambos lados.

La diferencia restante es ergonómica, no semántica. «Mismo visitante» es una función de clave para uniqBy(v) => v.user — mientras que distinctUnique pide una pareja acompasada de equals + hashCode, dos closures que deben estar de acuerdo entre sí. Eso es una molestia leve, no un hueco de modelo, y el main asíncrono es la sobrecarga de stream habitual sobre datos fijos. Veredicto: empate — el operador de deduplicación global existe en ambos lados y se comporta igual.

Benchmark

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

N = 100

Tiempo Empate

RxDart 13 µs
FxDart 4.7 µs

Memoria pico Empate

RxDart 16.7 MB
FxDart 16.5 MB

N = 1,000,000

Tiempo Gana FxDart

RxDart 294.6 ms
FxDart 84.8 ms

Memoria pico Empate

RxDart 209.0 MB
FxDart 200.7 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í.