가장 큰 지출 상위 3건

우열 없음

요구사항

한 달치 지출 중 가장 큰 세 건을 판매자와 금액으로, 큰 금액부터 순서대로 출력하세요. 데이터는 아래 코드에 있으며, 두 버전 모두 예상 출력 아래에 표시된 줄들을 출력해야 합니다.

예상 출력
Airline Ticket  $289.99
New Headphones  $129.00
Electric Co     $60.34

나란히 보기

네이티브 Dart

FxDart

차이가 나는 이유

거의 차이가 없습니다 — 페이지 위의 코드는 무승부입니다. 양쪽 모두 부호를 반전한 키로 정렬해 내림차순을 얻고 앞의 세 개를 취합니다. package:collectionsortedBy는 FxDart의 sortBy만큼이나 직접적입니다(Dart 코어의 List.sort만 단독으로 쓰면 제자리에서 변형되고 명시적인 비교자가 필요하지만, collection은 표준적인 의존성입니다). 나열된 코드에서 실질적인 차이는 그 어휘가 어디에 있느냐뿐입니다 — 패키지의 확장 메서드냐, 아니면 scan, chunk, 비동기 변형까지 함께 제공하는 체인의 한 단계냐. 어느 쪽을 골라도 떳떳합니다.

나열된 코드는 무승부지만 시계는 아닙니다. 100만 행에서 아래 막대는 FxDart가 약 2.6배 빠릅니다(200 ms 대 521 ms). 더 영리한 빅오 때문이 아닙니다 — 양쪽 모두 리스트를 복사한 뒤 안정적인 O(n log n) 병합 정렬을 돌립니다. 차이는 비교 한 번의 비용입니다.

네이티브 sortedBy는 collection의 mergeSortBy입니다. 을 정렬하면서 키 추출 함수를 비교할 때마다 호출합니다. 100만 행이면 (t) => -t.amount를 약 2,000만 번 호출합니다. 키 타입은 제네릭 K extends Comparable — 여기서는 num — 이라 그 키는 전부 힙에 박싱된 double이고, 가상 compareTo를 거쳐 비교됩니다.

FxDart의 sortBy는 먼저 추출합니다. 리스트를 한 번 훑어 모든 키가 double임을 보고 Float64List에 씁니다. 그다음 키와 행을 함께, 순차적으로 병합합니다. 비교 한 번은 타입 배열에서 꺼낸 기계 double 두 개이고, 이 데이터에서는 VM 비교를 씁니다(금액이 보통의 유한 양수라 NaN이나 -0.0이 없어 느린 compareTo 경로로 떨어지지 않습니다). 행마다 추출 한 번, 박싱 없음, 디스패치 없음, 인덱스로 키를 쫓아다니는 일도 없습니다. 예전 sortBy는 인덱스 목록을 List.sort로 정렬하는 데코레이트였습니다. 그건 사라졌습니다. 지금 병합은 구조적으로 안정적입니다 — 키가 같은 행은 이제 양쪽 모두 입력 순서를 지킵니다.

한계도 정직하게 말하면 이렇습니다: 키가 전부 double, int, String 중 하나로 균일하지 않으면 sortBy는 제네릭 비교자로 되돌아가고 이 이점은 사라집니다. 100만 행에서 메모리는 비슷합니다(약 123 MB 대 130 MB) — 양쪽 모두 행 복사본과 스크래치 버퍼를 붙들고 있습니다. 이 예제는 금액이 모두 달라서, 안정성은 출력되는 세 줄에는 드러나지 않습니다.

벤치마크

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

N = 100

시간 무승부

네이티브 Dart 20 µs
FxDart 5.6 µs

최대 메모리 무승부

네이티브 Dart 16.6 MB
FxDart 16.5 MB

N = 10,000

시간 FxDart 승

네이티브 Dart 3.31 ms
FxDart 846 µs

최대 메모리 FxDart 승

네이티브 Dart 23.2 MB
FxDart 21.4 MB

N = 1,000,000

시간 FxDart 승

네이티브 Dart 521.1 ms
FxDart 199.6 ms

최대 메모리 네이티브 승

네이티브 Dart 123.2 MB
FxDart 129.7 MB

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