Obtener perfiles de dos en dos

Gana FxDart async

Requisito

Obtén seis perfiles de usuario de una API (simulada), pero sin superar nunca dos peticiones en curso a la vez: la API limita la tasa de peticiones. Los resultados deben volver en el orden original. Para demostrar que el límite se respetó, la petición falsa cuenta cuántas peticiones se solapan y ambas versiones imprimen el máximo observado.

Esta es la tarea para la que Dart nativo no tiene ninguna primitiva. Future.wait lo lanza todo a la vez; agrupar en parejas desperdicia tiempo esperando a la más lenta de cada pareja; hacerlo bien significa escribir un pool de workers a mano —llevar la cuenta de los índices, un cursor compartido, huecos de resultado predimensionados—. El .concurrent(2) de FxDart es ese pool de workers, en una sola palabra: en cuanto termina una petición arranca la siguiente, y el orden se conserva.

Salida esperada
user#1, user#2, user#3, user#4, user#5, user#6
max requests in flight: 2

Lado a lado

Dart nativo

FxDart

Por qué difieren

Las dos versiones imprimen lo mismo —la diferencia está en lo que has tenido que escribir y en lo que ahora tienes que mantener. El pool de workers nativo es boilerplate de producción de verdad (y es fácil equivocarse sutilmente: un off-by-one en el cursor compartido, olvidar predimensionar la lista de resultados, perder el orden). En la versión de FxDart la política de concurrencia es un único paso de la cadena, así que cambiar el límite —o quitarlo— toca un número en lugar de toda la forma de la función.

Benchmark

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

Caso async: la escala principal es N = 100,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

Dart nativo 323 µs
FxDart 360 µs

Memoria pico Empate

Dart nativo 16.5 MB
FxDart 17.0 MB

N = 10,000

Tiempo Gana nativo

Dart nativo 31.1 ms
FxDart 34.6 ms

Memoria pico Gana FxDart

Dart nativo 26.1 MB
FxDart 22.2 MB

N = 100,000

Tiempo Gana nativo

Dart nativo 305.9 ms
FxDart 339.2 ms

Memoria pico Empate

Dart nativo 49.3 MB
FxDart 50.1 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í.