feat(collection): Replace quickSort with pdqsort for performance and robustness (#922)

Co-authored-by: Nate Bosch <nbosch1@gmail.com>
diff --git a/pkgs/collection/CHANGELOG.md b/pkgs/collection/CHANGELOG.md
index 6517421..5773f47 100644
--- a/pkgs/collection/CHANGELOG.md
+++ b/pkgs/collection/CHANGELOG.md
@@ -11,6 +11,8 @@
 - Add `PriorityQueue.of` constructor and optimize adding many elements.
 - Address diagnostics from `strict_top_level_inference`.
 - Run `dart format` with the new style.
+- Replace `quickSort` implementation with a more performant and robust
+  Pattern-defeating Quicksort (pdqsort) algorithm.
 
 ## 1.19.1
 
diff --git a/pkgs/collection/benchmark/benchmark_utils.dart b/pkgs/collection/benchmark/benchmark_utils.dart
new file mode 100644
index 0000000..d819868
--- /dev/null
+++ b/pkgs/collection/benchmark/benchmark_utils.dart
@@ -0,0 +1,235 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Reusable utilities for benchmarking sorting algorithms.
+library;
+
+import 'dart:math';
+import 'package:benchmark_harness/benchmark_harness.dart';
+
+// Sink variable to prevent the compiler from optimizing away benchmark code.
+int sink = 0;
+
+/// The aggregated result of a benchmark run.
+class BenchmarkResult {
+  final double mean;
+  final int median;
+  final double stdDev;
+  final List<int> allTimes;
+
+  BenchmarkResult(this.mean, this.median, this.stdDev, this.allTimes);
+}
+
+/// Base class for sorting benchmarks with dataset generation.
+abstract class SortBenchmarkBase extends BenchmarkBase {
+  final int size;
+  late final List<List<int>> _datasets;
+  int _iteration = 0;
+  int _checksum = 0;
+
+  SortBenchmarkBase(super.name, this.size);
+
+  /// Generate datasets for this benchmark condition.
+  List<List<int>> generateDatasets();
+
+  @override
+  void setup() {
+    _datasets = generateDatasets();
+  }
+
+  /// Get the next list to sort (creates a copy).
+  List<int> get nextList {
+    final dataset = _datasets[_iteration];
+    _iteration++;
+    if (_iteration == _datasets.length) _iteration = 0;
+    return dataset.toList();
+  }
+
+  /// Update checksum to prevent compiler optimization.
+  void updateChecksum(List<int> list) {
+    sink ^= list.first ^ list.last ^ list[list.length >> 1] ^ _checksum++;
+  }
+
+  /// The core sorting operation to benchmark.
+  void performSort();
+
+  @override
+  void run() => performSort();
+}
+
+/// Data pattern generators for consistent testing.
+class DatasetGenerators {
+  /// Generate random integer lists.
+  static List<List<int>> random(int size, {int count = 128, int? seed}) {
+    final r = Random(seed ?? 12345);
+    return List.generate(
+        count, (_) => List.generate(size, (_) => r.nextInt(size)));
+  }
+
+  /// Generate sorted lists.
+  static List<List<int>> sorted(int size) {
+    return [List.generate(size, (i) => i, growable: true)];
+  }
+
+  /// Generate reverse-sorted lists.
+  static List<List<int>> reverse(int size) {
+    return [List.generate(size, (i) => size - i - 1, growable: true)];
+  }
+
+  /// Generate lists with few unique values.
+  static List<List<int>> fewUnique(int size,
+      {int uniqueCount = 7, int count = 128, int? seed}) {
+    final r = Random(seed ?? 67890);
+    return List.generate(
+        count, (_) => List.generate(size, (_) => r.nextInt(uniqueCount)));
+  }
+
+  /// Generate pathological input (worst-case for naive quicksort).
+  /// Contains even-indexed elements followed by odd-indexed in reverse.
+  static List<List<int>> pathological(int size) {
+    final sorted = List.generate(size, (i) => i, growable: false);
+    final secondLoopStart = (size - 1).isOdd ? size - 1 : size - 2;
+    final pathological = [
+      for (var i = 0; i < size; i += 2) sorted[i],
+      for (var i = secondLoopStart; i > -1; i -= 2) sorted[i],
+    ];
+    return [pathological];
+  }
+
+  /// Generate nearly sorted lists (only a few elements out of place).
+  static List<List<int>> nearlySorted(int size,
+      {double swapPercent = 0.05, int count = 128, int? seed}) {
+    final r = Random(seed ?? 11111);
+    return List.generate(count, (_) {
+      final list = List.generate(size, (i) => i, growable: true);
+      final numSwaps = (size * swapPercent).round();
+      for (var i = 0; i < numSwaps; i++) {
+        final idx1 = r.nextInt(size);
+        final idx2 = r.nextInt(size);
+        final temp = list[idx1];
+        list[idx1] = list[idx2];
+        list[idx2] = temp;
+      }
+      return list;
+    });
+  }
+}
+
+/// Run a benchmark multiple times and collect statistics.
+BenchmarkResult runBenchmark(SortBenchmarkBase benchmark, int samples) {
+  final times = <int>[];
+
+  // Setup datasets
+  benchmark.setup();
+
+  // Warmup runs (not timed)
+  for (var i = 0; i < 3; i++) {
+    benchmark.run();
+  }
+
+  // Timed runs
+  for (var i = 0; i < samples; i++) {
+    final stopwatch = Stopwatch()..start();
+    benchmark.run();
+    stopwatch.stop();
+    times.add(stopwatch.elapsedMicroseconds);
+  }
+
+  times.sort();
+  final mean = times.reduce((a, b) => a + b) / samples;
+  final median = times[samples >> 1];
+
+  // Calculate standard deviation
+  final variance =
+      times.map((t) => pow(t - mean, 2)).reduce((a, b) => a + b) / samples;
+  final stdDev = sqrt(variance);
+
+  return BenchmarkResult(mean, median, stdDev, times);
+}
+
+/// Print benchmark results as a markdown table.
+///
+/// [baselineName] and [comparisonName] are the labels for the
+/// two implementations
+/// being compared (e.g., "Legacy", "pdqsort", "MergeSort", etc.).
+void printResultsAsMarkdownTable(
+    Map<String, (BenchmarkResult, BenchmarkResult)> results, int size,
+    {required String baselineName,
+    required String comparisonName,
+    bool showStdDev = false}) {
+  final separator = '=' * 100;
+  print('\n$separator');
+  print('Benchmark Results (Size: $size): $comparisonName vs. $baselineName');
+  print(separator);
+
+  // Calculate dynamic column widths based on name lengths
+  final baselineColWidth = max(baselineName.length + 5, 13);
+  final comparisonColWidth = max(comparisonName.length + 5, 13);
+
+  final baselineHeader = '$baselineName (µs)'.padRight(baselineColWidth);
+  final comparisonHeader = '$comparisonName (µs)'.padRight(comparisonColWidth);
+
+  if (showStdDev) {
+    print(
+        '''| Data Condition      | $baselineHeader | $comparisonHeader | Improvement | StdDev        |''');
+    print(
+        '''| :------------------ | :${'-' * (baselineColWidth - 2)}: | :${'-' * (comparisonColWidth - 2)}: | :---------: | :-----------: |''');
+  } else {
+    print(
+        '''| Data Condition      | $baselineHeader | $comparisonHeader | Improvement | Winner          |''');
+    print(
+        '''| :------------------ | :${'-' * (baselineColWidth - 2)}: | :${'-' * (comparisonColWidth - 2)}: | :---------: | :-------------: |''');
+  }
+
+  print(
+      '''| **Mean**            | ${' ' * baselineColWidth} | ${' ' * comparisonColWidth} |             |                 |''');
+
+  for (final entry in results.entries) {
+    final condition = entry.key;
+    final (baseline, comparison) = entry.value;
+
+    final improvement = (baseline.mean - comparison.mean) / baseline.mean * 100;
+    final improvementString =
+        '${improvement > 0 ? '+' : ''}${improvement.toStringAsFixed(2)}%';
+    final baselineMean = baseline.mean.round().toString();
+    final comparisonMean = comparison.mean.round().toString();
+
+    if (showStdDev) {
+      final stdDevString =
+          '${baseline.stdDev.round()}/${comparison.stdDev.round()}';
+      print(
+          '''| ${condition.padRight(19)} | ${baselineMean.padLeft(baselineColWidth)} | ${comparisonMean.padLeft(comparisonColWidth)} | ${improvementString.padLeft(11)} | ${stdDevString.padLeft(13)} |''');
+    } else {
+      final winner = improvement > 0 ? '$comparisonName 🚀' : baselineName;
+      print(
+          '''| ${condition.padRight(19)} | ${baselineMean.padLeft(baselineColWidth)} | ${comparisonMean.padLeft(comparisonColWidth)} | ${improvementString.padLeft(11)} | ${winner.padLeft(15)} |''');
+    }
+  }
+
+  print(
+      '''| **Median**          | ${' ' * baselineColWidth} | ${' ' * comparisonColWidth} |             |                 |''');
+
+  for (final entry in results.entries) {
+    final condition = entry.key;
+    final (baseline, comparison) = entry.value;
+
+    final improvement =
+        (baseline.median - comparison.median) / baseline.median * 100;
+    final improvementString =
+        '${improvement > 0 ? '+' : ''}${improvement.toStringAsFixed(2)}%';
+    final baselineMedian = baseline.median.toString();
+    final comparisonMedian = comparison.median.toString();
+
+    if (showStdDev) {
+      print(
+          '''| ${condition.padRight(19)} | ${baselineMedian.padLeft(baselineColWidth)} | ${comparisonMedian.padLeft(comparisonColWidth)} | ${improvementString.padLeft(11)} | ${' '.padLeft(13)} |''');
+    } else {
+      final winner = improvement > 0 ? '$comparisonName 🚀' : baselineName;
+      print(
+          '''| ${condition.padRight(19)} | ${baselineMedian.padLeft(baselineColWidth)} | ${comparisonMedian.padLeft(comparisonColWidth)} | ${improvementString.padLeft(11)} | ${winner.padLeft(15)} |''');
+    }
+  }
+
+  print(separator);
+}
diff --git a/pkgs/collection/benchmark/legacy_quicksort.dart b/pkgs/collection/benchmark/legacy_quicksort.dart
new file mode 100644
index 0000000..e27f468
--- /dev/null
+++ b/pkgs/collection/benchmark/legacy_quicksort.dart
@@ -0,0 +1,122 @@
+/// Legacy quickSort implementation preserved for benchmarking purposes.
+/// This code is ONLY for benchmarking and should not be used in production.
+library;
+
+import 'dart:math';
+import 'package:collection/src/utils.dart';
+
+/// Performs an insertion sort into a potentially different list than the
+/// one containing the original values.
+///
+/// It will work in-place as well.
+void _movingInsertionSort<E, K>(
+  List<E> list,
+  K Function(E element) keyOf,
+  int Function(K, K) compare,
+  int start,
+  int end,
+  List<E> target,
+  int targetOffset,
+) {
+  var length = end - start;
+  if (length == 0) return;
+  target[targetOffset] = list[start];
+  for (var i = 1; i < length; i++) {
+    var element = list[start + i];
+    var elementKey = keyOf(element);
+    var min = targetOffset;
+    var max = targetOffset + i;
+    while (min < max) {
+      var mid = min + ((max - min) >> 1);
+      if (compare(elementKey, keyOf(target[mid])) < 0) {
+        max = mid;
+      } else {
+        min = mid + 1;
+      }
+    }
+    target.setRange(min + 1, targetOffset + i + 1, target, min);
+    target[min] = element;
+  }
+}
+
+/// Sort [elements] using a quick-sort algorithm.
+///
+/// The elements are compared using [compare] on the elements.
+/// If [start] and [end] are provided, only that range is sorted.
+///
+/// Uses insertion sort for smaller sublists.
+void quickSort<E>(
+  List<E> elements,
+  int Function(E a, E b) compare, [
+  int start = 0,
+  int? end,
+]) {
+  end = RangeError.checkValidRange(start, end, elements.length);
+  _quickSort<E, E>(elements, identity, compare, Random(), start, end);
+}
+
+/// Sort [list] using a quick-sort algorithm.
+///
+/// The elements are compared using [compare] on the value provided by [keyOf]
+/// on the element.
+/// If [start] and [end] are provided, only that range is sorted.
+///
+/// Uses insertion sort for smaller sublists.
+void quickSortBy<E, K>(
+  List<E> list,
+  K Function(E element) keyOf,
+  int Function(K a, K b) compare, [
+  int start = 0,
+  int? end,
+]) {
+  end = RangeError.checkValidRange(start, end, list.length);
+  _quickSort(list, keyOf, compare, Random(), start, end);
+}
+
+void _quickSort<E, K>(
+  List<E> list,
+  K Function(E element) keyOf,
+  int Function(K a, K b) compare,
+  Random random,
+  int start,
+  int end,
+) {
+  const minQuickSortLength = 24;
+  var length = end - start;
+  while (length >= minQuickSortLength) {
+    var pivotIndex = random.nextInt(length) + start;
+    var pivot = list[pivotIndex];
+    var pivotKey = keyOf(pivot);
+    var endSmaller = start;
+    var startGreater = end;
+    var startPivots = end - 1;
+    list[pivotIndex] = list[startPivots];
+    list[startPivots] = pivot;
+    while (endSmaller < startPivots) {
+      var current = list[endSmaller];
+      var relation = compare(keyOf(current), pivotKey);
+      if (relation < 0) {
+        endSmaller++;
+      } else {
+        startPivots--;
+        var currentTarget = startPivots;
+        list[endSmaller] = list[startPivots];
+        if (relation > 0) {
+          startGreater--;
+          currentTarget = startGreater;
+          list[startPivots] = list[startGreater];
+        }
+        list[currentTarget] = current;
+      }
+    }
+    if (endSmaller - start < end - startGreater) {
+      _quickSort(list, keyOf, compare, random, start, endSmaller);
+      start = startGreater;
+    } else {
+      _quickSort(list, keyOf, compare, random, startGreater, end);
+      end = endSmaller;
+    }
+    length = end - start;
+  }
+  _movingInsertionSort<E, K>(list, keyOf, compare, start, end, list, start);
+}
diff --git a/pkgs/collection/benchmark/sort_benchmark.dart b/pkgs/collection/benchmark/sort_benchmark.dart
new file mode 100644
index 0000000..d76f9aa
--- /dev/null
+++ b/pkgs/collection/benchmark/sort_benchmark.dart
@@ -0,0 +1,243 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Benchmarks comparing the new pdqsort implementation against the baseline.
+/// This code is ONLY for benchmarking and should not be used in production.
+library;
+
+import 'package:collection/src/algorithms.dart' show quickSort;
+import 'benchmark_utils.dart';
+import 'legacy_quicksort.dart' as legacy;
+
+// --- Legacy Benchmarks (Old quickSort) ---
+
+class LegacyRandomBenchmark extends SortBenchmarkBase {
+  LegacyRandomBenchmark(int size) : super('Legacy.Random', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.random(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    legacy.quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class LegacySortedBenchmark extends SortBenchmarkBase {
+  LegacySortedBenchmark(int size) : super('Legacy.Sorted', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.sorted(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    legacy.quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class LegacyReverseBenchmark extends SortBenchmarkBase {
+  LegacyReverseBenchmark(int size) : super('Legacy.Reverse', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.reverse(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    legacy.quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class LegacyFewUniqueBenchmark extends SortBenchmarkBase {
+  LegacyFewUniqueBenchmark(int size) : super('Legacy.FewUnique', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.fewUnique(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    legacy.quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class LegacyPathologicalBenchmark extends SortBenchmarkBase {
+  LegacyPathologicalBenchmark(int size) : super('Legacy.Pathological', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.pathological(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    legacy.quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class LegacyNearlySortedBenchmark extends SortBenchmarkBase {
+  LegacyNearlySortedBenchmark(int size) : super('Legacy.NearlySorted', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.nearlySorted(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    legacy.quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+// --- Enhancement Benchmarks (New pdqsort) ---
+
+class EnhancementRandomBenchmark extends SortBenchmarkBase {
+  EnhancementRandomBenchmark(int size) : super('Enhancement.Random', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.random(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class EnhancementSortedBenchmark extends SortBenchmarkBase {
+  EnhancementSortedBenchmark(int size) : super('Enhancement.Sorted', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.sorted(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class EnhancementReverseBenchmark extends SortBenchmarkBase {
+  EnhancementReverseBenchmark(int size) : super('Enhancement.Reverse', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.reverse(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class EnhancementFewUniqueBenchmark extends SortBenchmarkBase {
+  EnhancementFewUniqueBenchmark(int size)
+      : super('Enhancement.FewUnique', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.fewUnique(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class EnhancementPathologicalBenchmark extends SortBenchmarkBase {
+  EnhancementPathologicalBenchmark(int size)
+      : super('Enhancement.Pathological', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.pathological(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+class EnhancementNearlySortedBenchmark extends SortBenchmarkBase {
+  EnhancementNearlySortedBenchmark(int size)
+      : super('Enhancement.NearlySorted', size);
+
+  @override
+  List<List<int>> generateDatasets() => DatasetGenerators.nearlySorted(size);
+
+  @override
+  void performSort() {
+    final list = nextList;
+    quickSort(list, (a, b) => a.compareTo(b));
+    updateChecksum(list);
+  }
+}
+
+// --- Main ---
+
+void main(List<String> args) {
+  const samples = 12;
+
+  // Support multiple sizes via command-line args or use default
+  final sizes = args.isEmpty ? [50000] : args.map(int.parse).toList();
+
+  for (final size in sizes) {
+    print('\n${'=' * 80}');
+    print('Running benchmarks with size: $size');
+    print('=' * 80);
+
+    final benchmarks = [
+      ('Random', LegacyRandomBenchmark(size), EnhancementRandomBenchmark(size)),
+      ('Sorted', LegacySortedBenchmark(size), EnhancementSortedBenchmark(size)),
+      (
+        'Reverse Sorted',
+        LegacyReverseBenchmark(size),
+        EnhancementReverseBenchmark(size)
+      ),
+      (
+        'Few Unique',
+        LegacyFewUniqueBenchmark(size),
+        EnhancementFewUniqueBenchmark(size)
+      ),
+      (
+        'Nearly Sorted',
+        LegacyNearlySortedBenchmark(size),
+        EnhancementNearlySortedBenchmark(size)
+      ),
+      (
+        'Pathological',
+        LegacyPathologicalBenchmark(size),
+        EnhancementPathologicalBenchmark(size)
+      ),
+    ];
+
+    final results = <String, (BenchmarkResult, BenchmarkResult)>{};
+
+    print('Running benchmarks ($samples samples each)...');
+    for (final (condition, legacy, enhancement) in benchmarks) {
+      print('  Testing $condition...');
+      final legacyResult = runBenchmark(legacy, samples);
+      final enhancementResult = runBenchmark(enhancement, samples);
+      results[condition] = (legacyResult, enhancementResult);
+    }
+
+    printResultsAsMarkdownTable(
+      results,
+      size,
+      baselineName: 'Legacy',
+      comparisonName: 'pdqsort',
+    );
+  }
+}
diff --git a/pkgs/collection/lib/src/algorithms.dart b/pkgs/collection/lib/src/algorithms.dart
index 88d1c4f..70430b9 100644
--- a/pkgs/collection/lib/src/algorithms.dart
+++ b/pkgs/collection/lib/src/algorithms.dart
@@ -482,12 +482,10 @@
   );
 }
 
-/// Sort [elements] using a quick-sort algorithm.
+/// Sorts a list between [start] (inclusive) and [end] (exclusive).
 ///
-/// The elements are compared using [compare] on the elements.
-/// If [start] and [end] are provided, only that range is sorted.
-///
-/// Uses insertion sort for smaller sublists.
+/// The sorting algorithm is a Pattern-defeating Quicksort (pdqsort), a
+/// hybrid of Quicksort, Heapsort, and Insertion Sort.
 void quickSort<E>(
   List<E> elements,
   int Function(E a, E b) compare, [
@@ -495,71 +493,392 @@
   int? end,
 ]) {
   end = RangeError.checkValidRange(start, end, elements.length);
-  _quickSort<E, E>(elements, identity, compare, Random(), start, end);
+  if (end - start < 2) return;
+  _pdqSortImpl(elements, compare, start, end, _log2(end - start));
 }
 
-/// Sort [list] using a quick-sort algorithm.
+/// Sorts a list between [start] (inclusive) and [end] (exclusive) by key.
 ///
-/// The elements are compared using [compare] on the value provided by [keyOf]
-/// on the element.
-/// If [start] and [end] are provided, only that range is sorted.
-///
-/// Uses insertion sort for smaller sublists.
+/// Elements are ordered by the [compare] function applied to the result of
+/// the [keyOf] function.
 void quickSortBy<E, K>(
-  List<E> list,
+  List<E> elements,
   K Function(E element) keyOf,
   int Function(K a, K b) compare, [
   int start = 0,
   int? end,
 ]) {
-  end = RangeError.checkValidRange(start, end, list.length);
-  _quickSort(list, keyOf, compare, Random(), start, end);
+  end = RangeError.checkValidRange(start, end, elements.length);
+  if (end - start < 2) return;
+  _pdqSortByImpl(elements, keyOf, compare, start, end, _log2(end - start));
 }
 
-void _quickSort<E, K>(
-  List<E> list,
-  K Function(E element) keyOf,
-  int Function(K a, K b) compare,
-  Random random,
-  int start,
-  int end,
-) {
-  const minQuickSortLength = 24;
-  var length = end - start;
-  while (length >= minQuickSortLength) {
-    var pivotIndex = random.nextInt(length) + start;
-    var pivot = list[pivotIndex];
-    var pivotKey = keyOf(pivot);
-    var endSmaller = start;
-    var startGreater = end;
-    var startPivots = end - 1;
-    list[pivotIndex] = list[startPivots];
-    list[startPivots] = pivot;
-    while (endSmaller < startPivots) {
-      var current = list[endSmaller];
-      var relation = compare(keyOf(current), pivotKey);
-      if (relation < 0) {
-        endSmaller++;
+/// Minimum list size below which pdqsort uses insertion sort.
+const int _pdqInsertionSortThreshold = 32;
+
+/// Computes the base-2 logarithm of [n].
+///
+/// Uses bitLength to compute the floor(log2(n)) efficiently.
+/// For n == 0 we return 0.
+int _log2(int n) => n > 0 ? n.bitLength - 1 : 0;
+
+// ==========================================
+// Implementation: Direct Comparison
+// ==========================================
+
+void _pdqSortImpl<E>(List<E> elements, int Function(E, E) compare, int start,
+    int end, int badAllowed) {
+  while (true) {
+    final size = end - start;
+    if (size < _pdqInsertionSortThreshold) {
+      _insertionSort(elements, compare, start, end);
+      return;
+    }
+
+    if (_handlePresorted(elements, compare, start, end)) return;
+
+    if (badAllowed == 0) {
+      _heapSort(elements, compare, start, end);
+      return;
+    }
+
+    final mid = start + size ~/ 2;
+    _selectPivot(elements, compare, start, mid, end, size);
+
+    final pivot = elements[start];
+    var less = start;
+    var equal = start + 1;
+    var greater = end;
+
+    while (equal < greater) {
+      final element = elements[equal];
+      final comparison = compare(element, pivot);
+
+      if (comparison < 0) {
+        elements[equal] = elements[less];
+        elements[less] = element;
+        less++;
+        equal++;
+      } else if (comparison > 0) {
+        greater--;
+        elements[equal] = elements[greater];
+        elements[greater] = element;
       } else {
-        startPivots--;
-        var currentTarget = startPivots;
-        list[endSmaller] = list[startPivots];
-        if (relation > 0) {
-          startGreater--;
-          currentTarget = startGreater;
-          list[startPivots] = list[startGreater];
-        }
-        list[currentTarget] = current;
+        equal++;
       }
     }
-    if (endSmaller - start < end - startGreater) {
-      _quickSort(list, keyOf, compare, random, start, endSmaller);
-      start = startGreater;
-    } else {
-      _quickSort(list, keyOf, compare, random, startGreater, end);
-      end = endSmaller;
+
+    if ((less - start) < size ~/ 8 || (end - greater) < size ~/ 8) {
+      badAllowed--;
     }
-    length = end - start;
+
+    if (less - start < end - greater) {
+      _pdqSortImpl(elements, compare, start, less, badAllowed);
+      start = greater;
+    } else {
+      _pdqSortImpl(elements, compare, greater, end, badAllowed);
+      end = less;
+    }
   }
-  _movingInsertionSort<E, K>(list, keyOf, compare, start, end, list, start);
+}
+
+bool _handlePresorted<E>(
+    List<E> elements, int Function(E, E) compare, int start, int end) {
+  if (compare(elements[start], elements[start + 1]) > 0) {
+    // Check strictly decreasing
+    var i = start + 1;
+    while (i < end && compare(elements[i - 1], elements[i]) >= 0) {
+      i++;
+    }
+    if (i == end) {
+      _reverseRange(elements, start, end);
+      return true;
+    }
+  } else {
+    // Check non-decreasing
+    var i = start + 1;
+    while (i < end && compare(elements[i - 1], elements[i]) <= 0) {
+      i++;
+    }
+    if (i == end) return true;
+  }
+  return false;
+}
+
+void _reverseRange<E>(List<E> elements, int start, int end) {
+  var left = start;
+  var right = end - 1;
+  while (left < right) {
+    final temp = elements[left];
+    elements[left] = elements[right];
+    elements[right] = temp;
+    left++;
+    right--;
+  }
+}
+
+void _insertionSort<E>(
+    List<E> elements, int Function(E, E) compare, int start, int end) {
+  for (var i = start + 1; i < end; i++) {
+    var current = elements[i];
+    var j = i - 1;
+    while (j >= start && compare(elements[j], current) > 0) {
+      elements[j + 1] = elements[j];
+      j--;
+    }
+    elements[j + 1] = current;
+  }
+}
+
+void _heapSort<E>(
+    List<E> elements, int Function(E, E) compare, int start, int end) {
+  final n = end - start;
+  for (var i = n ~/ 2 - 1; i >= 0; i--) {
+    _siftDown(elements, compare, i, n, start);
+  }
+  for (var i = n - 1; i > 0; i--) {
+    final temp = elements[start];
+    elements[start] = elements[start + i];
+    elements[start + i] = temp;
+    _siftDown(elements, compare, 0, i, start);
+  }
+}
+
+void _siftDown<E>(
+    List<E> elements, int Function(E, E) compare, int i, int n, int start) {
+  var root = i;
+  while (true) {
+    final left = 2 * root + 1;
+    if (left >= n) break;
+    var largest = root;
+    if (compare(elements[start + left], elements[start + largest]) > 0) {
+      largest = left;
+    }
+    final right = left + 1;
+    if (right < n &&
+        compare(elements[start + right], elements[start + largest]) > 0) {
+      largest = right;
+    }
+    if (largest == root) break;
+    final temp = elements[start + root];
+    elements[start + root] = elements[start + largest];
+    elements[start + largest] = temp;
+    root = largest;
+  }
+}
+
+void _selectPivot<E>(List<E> elements, int Function(E, E) compare, int start,
+    int mid, int end, int size) {
+  if (size > 80) {
+    final s = size ~/ 8;
+    _sort3(elements, compare, start, start + s, start + 2 * s);
+    _sort3(elements, compare, mid - s, mid, mid + s);
+    _sort3(elements, compare, end - 1 - 2 * s, end - 1 - s, end - 1);
+    _sort3(elements, compare, start + s, mid, end - 1 - s);
+  } else {
+    _sort3(elements, compare, start, mid, end - 1);
+  }
+  final temp = elements[start];
+  elements[start] = elements[mid];
+  elements[mid] = temp;
+}
+
+void _sort3<E>(
+    List<E> elements, int Function(E, E) compare, int a, int b, int c) {
+  if (compare(elements[a], elements[b]) > 0) {
+    final t = elements[a];
+    elements[a] = elements[b];
+    elements[b] = t;
+  }
+  if (compare(elements[b], elements[c]) > 0) {
+    final t = elements[b];
+    elements[b] = elements[c];
+    elements[c] = t;
+    if (compare(elements[a], elements[b]) > 0) {
+      final t2 = elements[a];
+      elements[a] = elements[b];
+      elements[b] = t2;
+    }
+  }
+}
+
+// ==========================================
+// Implementation: Keyed Comparison (By)
+// ==========================================
+
+/// [badAllowed] tracks how many bad pivot selections are allowed before
+/// falling back to heap sort.
+void _pdqSortByImpl<E, K>(List<E> elements, K Function(E) keyOf,
+    int Function(K, K) compare, int start, int end, int badAllowed) {
+  while (true) {
+    final size = end - start;
+    if (size < _pdqInsertionSortThreshold) {
+      _insertionSortBy(elements, keyOf, compare, start, end);
+      return;
+    }
+
+    if (_handlePresortedBy(elements, keyOf, compare, start, end)) return;
+
+    if (badAllowed == 0) {
+      _heapSortBy(elements, keyOf, compare, start, end);
+      return;
+    }
+
+    final mid = start + size ~/ 2;
+    _selectPivotBy(elements, keyOf, compare, start, mid, end, size);
+
+    final pivotElement = elements[start];
+    final pivotKey = keyOf(pivotElement);
+
+    var less = start;
+    var equal = start + 1;
+    var greater = end;
+
+    while (equal < greater) {
+      final element = elements[equal];
+      final elementKey = keyOf(element);
+      final comparison = compare(elementKey, pivotKey);
+
+      if (comparison < 0) {
+        elements[equal] = elements[less];
+        elements[less] = element;
+        less++;
+        equal++;
+      } else if (comparison > 0) {
+        greater--;
+        elements[equal] = elements[greater];
+        elements[greater] = element;
+      } else {
+        equal++;
+      }
+    }
+
+    if ((less - start) < size ~/ 8 || (end - greater) < size ~/ 8) {
+      badAllowed--;
+    }
+
+    if (less - start < end - greater) {
+      _pdqSortByImpl(elements, keyOf, compare, start, less, badAllowed);
+      start = greater;
+    } else {
+      _pdqSortByImpl(elements, keyOf, compare, greater, end, badAllowed);
+      end = less;
+    }
+  }
+}
+
+bool _handlePresortedBy<E, K>(List<E> elements, K Function(E) keyOf,
+    int Function(K, K) compare, int start, int end) {
+  if (compare(keyOf(elements[start]), keyOf(elements[start + 1])) > 0) {
+    var i = start + 1;
+    while (
+        i < end && compare(keyOf(elements[i - 1]), keyOf(elements[i])) >= 0) {
+      i++;
+    }
+    if (i == end) {
+      _reverseRange(elements, start, end);
+      return true;
+    }
+  } else {
+    var i = start + 1;
+    while (
+        i < end && compare(keyOf(elements[i - 1]), keyOf(elements[i])) <= 0) {
+      i++;
+    }
+    if (i == end) return true;
+  }
+  return false;
+}
+
+void _insertionSortBy<E, K>(List<E> elements, K Function(E) keyOf,
+    int Function(K, K) compare, int start, int end) {
+  for (var i = start + 1; i < end; i++) {
+    final current = elements[i];
+    final currentKey = keyOf(current);
+    var j = i - 1;
+    while (j >= start && compare(keyOf(elements[j]), currentKey) > 0) {
+      elements[j + 1] = elements[j];
+      j--;
+    }
+    elements[j + 1] = current;
+  }
+}
+
+void _heapSortBy<E, K>(List<E> elements, K Function(E) keyOf,
+    int Function(K, K) compare, int start, int end) {
+  final n = end - start;
+  for (var i = n ~/ 2 - 1; i >= 0; i--) {
+    _siftDownBy(elements, keyOf, compare, i, n, start);
+  }
+  for (var i = n - 1; i > 0; i--) {
+    final temp = elements[start];
+    elements[start] = elements[start + i];
+    elements[start + i] = temp;
+    _siftDownBy(elements, keyOf, compare, 0, i, start);
+  }
+}
+
+void _siftDownBy<E, K>(List<E> elements, K Function(E) keyOf,
+    int Function(K, K) compare, int i, int n, int start) {
+  var root = i;
+  while (true) {
+    final left = 2 * root + 1;
+    if (left >= n) break;
+    var largest = root;
+    var largestKey = keyOf(elements[start + largest]);
+
+    final leftKey = keyOf(elements[start + left]);
+    if (compare(leftKey, largestKey) > 0) {
+      largest = left;
+      largestKey = leftKey;
+    }
+
+    final right = left + 1;
+    if (right < n) {
+      final rightKey = keyOf(elements[start + right]);
+      if (compare(rightKey, largestKey) > 0) {
+        largest = right;
+      }
+    }
+    if (largest == root) break;
+    final temp = elements[start + root];
+    elements[start + root] = elements[start + largest];
+    elements[start + largest] = temp;
+    root = largest;
+  }
+}
+
+void _selectPivotBy<E, K>(List<E> elements, K Function(E) keyOf,
+    int Function(K, K) compare, int start, int mid, int end, int size) {
+  if (size > 80) {
+    final s = size ~/ 8;
+    _sort3By(elements, keyOf, compare, start, start + s, start + 2 * s);
+    _sort3By(elements, keyOf, compare, mid - s, mid, mid + s);
+    _sort3By(elements, keyOf, compare, end - 1 - 2 * s, end - 1 - s, end - 1);
+    _sort3By(elements, keyOf, compare, start + s, mid, end - 1 - s);
+  } else {
+    _sort3By(elements, keyOf, compare, start, mid, end - 1);
+  }
+  final temp = elements[start];
+  elements[start] = elements[mid];
+  elements[mid] = temp;
+}
+
+void _sort3By<E, K>(List<E> elements, K Function(E) keyOf,
+    int Function(K, K) compare, int a, int b, int c) {
+  if (compare(keyOf(elements[a]), keyOf(elements[b])) > 0) {
+    final t = elements[a];
+    elements[a] = elements[b];
+    elements[b] = t;
+  }
+  if (compare(keyOf(elements[b]), keyOf(elements[c])) > 0) {
+    final t = elements[b];
+    elements[b] = elements[c];
+    elements[c] = t;
+    if (compare(keyOf(elements[a]), keyOf(elements[b])) > 0) {
+      final t2 = elements[a];
+      elements[a] = elements[b];
+      elements[b] = t2;
+    }
+  }
 }