private static void doReads(int threads, long items, ExternalMergeSort sorter) {
    var counters = Counter.newMultiThreadCounter();
    Iterable<SortableFeature> q = threads > 1 ? sorter.parallelIterator(Stats.inMemory(), threads) : sorter;
    var reader = new Worker("read", Stats.inMemory(), 1, () -> {
      var counter = counters.counterForThread();
      for (var ignored : q) {
        counter.inc();
      }
    });
    ProgressLoggers loggers = ProgressLoggers.create()
      .addRatePercentCounter("items", items, counters, false)
      .addFileSize(sorter)
      .newLine()
      .addProcessStats()
      .newLine();
    if (q instanceof FeatureSort.ParallelIterator pi) {
      loggers
        .addThreadPoolStats("read", pi.reader())
        .addThreadPoolStats("merge", reader);
    } else {
      loggers.addThreadPoolStats("read", reader);
    }
    reader.awaitAndLog(loggers, Duration.ofSeconds(1));
  }
Performance tests for {@link ExternalMergeSort}. Times how long it takes to write temp features, sort, then read them
back with different parameters.
<p>
Usage: {@code BenchmarkExternalMergeSort &lt;number of GB of features to write&gt;}
planetiler-benchmarks/src/main/java/com/onthegomap/planetiler/collection/BenchmarkExternalMergeSort.java