프로필 10개를 세 개씩 가져오기
요구사항
열두 개의 계정으로 이루어진 디렉터리에서 활성 계정만 골라 id 순으로 정렬한 뒤, (가상의) API에서 각 프로필을 가져오세요 — 동시에 진행 중인 요청이 세 개를 넘지 않아야 하며, 결과는 원래 순서대로 나와야 합니다. 가짜 fetch 함수는 겹쳐서 실행된 요청 수를 세고, 두 버전 모두 관측된 최댓값을 출력해 제한이 지켜졌음을 증명합니다. 데이터는 아래 코드에 있습니다.
이는 비동기 섹션 전체를 대표하는 형태입니다: 동기 파이프라인
(filter → sortBy)이 toAsync로
비동기 영역에 들어선 뒤에도 계속 이어집니다 — fetch를 실행하는
map, 이를 제한하는 concurrent(3), 형식을
맞추는 또 하나의 map, 마무리하는 join까지.
리스트에서 리포트까지 하나의 체인입니다.
예상 출력
fetched 10 profiles, 3 at a time: user#1 Ada <ada@example.com> user#2 Bram <bram@example.com> user#4 Dana <dana@example.com> user#5 Eli <eli@example.com> user#6 Fay <fay@example.com> user#7 Gus <gus@example.com> user#9 Ines <ines@example.com> user#10 Jun <jun@example.com> user#11 Kira <kira@example.com> user#12 Liam <liam@example.com> max requests in flight: 3
나란히 보기
네이티브 Dart
FxDart
차이가 나는 이유
순수 Dart는 동기 절반(where + sortedBy)은
잘 처리하지만, 비동기 경계에 이르면 어휘가 바닥납니다: 순서를
유지하면서 동시성을 제한하려면 직접 만든 워커 풀 — 공유 커서, 미리
크기를 정한 결과 슬롯, 워커들을 기다리는 Future.wait —
이 필요합니다. 그 풀은 실제 프로덕션에서 흔한 보일러플레이트이며,
작업을 두 개의 방언으로 쪼갭니다: 준비 과정을 위한 유려한 체인과,
fetch를 위한 명령형 배관 작업. FxDart 버전에서는 정책이 끝까지
선언적으로 유지됩니다 — concurrent(3)이 워커 풀 전체를
대신하며, 제한값을 바꾸거나 없애려면 함수의 구조가 아니라 숫자
하나만 건드리면 됩니다.
벤치마크
비동기 예제입니다. 대표 스케일이 1,000,000이 아니라 N = 100,000인 이유 — 원소 하나마다 양쪽 모두 이벤트 루프를 한 바퀴 돌아야 하므로, 실제 await 백만 번은 파이프라인이 아니라 Dart 이벤트 루프를 몇 분씩 재게 됩니다. 지연은 0으로 두고 예제의 동시성 제한은 그대로 유지합니다. 막대가 비교하는 것은 파이프라인 기계 장치 자체입니다.
N = 100
시간 무승부
최대 메모리 무승부
N = 10,000
시간 무승부
최대 메모리 FxDart 승
N = 100,000
시간 무승부
최대 메모리 무승부
막대는 사이드별로 새 프로세스에서 반복 측정한 중앙값입니다(작은 N은 타이머 해상도를 위해 배치 처리). 두 사이드가 서로 5% 이내이거나 — 사람이 지각할 수 없는 차이인 0.6ms 이내이면 — 무승부로 칩니다. 상대 차이가 근소한 경우는 최대 5회까지 다시 측정합니다. 앱에서는 어느 막대가 짧든 몇 밀리초 이하의 차이는 사용자에게 보이지 않습니다. 메모리는 프로세스 최대 RSS입니다. Dart VM과 데이터셋은 양쪽이 동일하므로, 두 막대의 차이가 곧 파이프라인 자체가 붙들고 있는 양입니다.