코호트 리텐션 테이블

FxDart 승

요구사항

각 사용자(데이터는 코드 안에 있음)는 가입월과 활동한 월의 목록을 갖고 있습니다. 사용자를 가입월 기준 코호트로 묶고, 그 이후의 각 월마다 코호트 중 몇 퍼센트가 여전히 활동 중이었는지 출력하세요 — 코호트당 한 줄씩, 오래된 순서로 정렬합니다. 두 버전 모두 예상 출력 아래에 표시된 테이블을 출력해야 합니다.

예상 출력
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%

나란히 보기

네이티브 Dart

FxDart

차이가 나는 이유

리텐션 테이블은 파이프라인 속의 파이프라인입니다: 바깥쪽은 코호트, 안쪽은 월입니다. FxDart에서는 두 계층 모두 표현식입니다 — 코호트에 대해서는 groupBysortBymap이 적용되고, 각 행 안에서는 dropWhile이 가입월까지의 달을 건너뛴 뒤 filter + size가 여전히 활동 중인 사용자 수를 셉니다. 네이티브 버전은 계층마다 가변 누산 리스트 (rows, cells)가 필요하고, 이를 엮기 위해 두 겹의 중첩 for 루프가 필요합니다. 실제 리텐션 로직은 동일하지만, 코드의 눈에 보이는 뼈대가 되는 대신 루프 본문 곳곳에 흩어져 있습니다.

벤치마크

Apple M1 Max, RAM 32 GB · Dart 3.12.2 (AOT 컴파일) · 2026-08-24

N = 100

시간 무승부

네이티브 Dart 47 µs
FxDart 37 µs

최대 메모리 무승부

네이티브 Dart 16.5 MB
FxDart 17.1 MB

N = 10,000

시간 무승부

네이티브 Dart 2.43 ms
FxDart 2.02 ms

최대 메모리 무승부

네이티브 Dart 17.5 MB
FxDart 18.3 MB

N = 1,000,000

시간 무승부

네이티브 Dart 717.6 ms
FxDart 722.8 ms

최대 메모리 무승부

네이티브 Dart 238.8 MB
FxDart 239.0 MB

막대는 사이드별로 새 프로세스에서 반복 측정한 중앙값입니다(작은 N은 타이머 해상도를 위해 배치 처리). 두 사이드가 서로 5% 이내이거나 — 사람이 지각할 수 없는 차이인 0.6ms 이내이면 — 무승부로 칩니다. 상대 차이가 근소한 경우는 최대 5회까지 다시 측정합니다. 앱에서는 어느 막대가 짧든 몇 밀리초 이하의 차이는 사용자에게 보이지 않습니다. 메모리는 프로세스 최대 RSS입니다. Dart VM과 데이터셋은 양쪽이 동일하므로, 두 막대의 차이가 곧 파이프라인 자체가 붙들고 있는 양입니다.