[libc-commits] [libc] [libc][stdlib] Optimize number of comparisons in heap_sort (PR #232602)

Kuan-Wei Chiu via libc-commits libc-commits at lists.llvm.org
Thu Oct 15 23:04:38 PDT 2026


visitorckw wrote:

I verified that all sorting related unit tests pass (libc.test.src.stdlib.heap_sort_test, libc.test.src.stdlib.quick_sort_test, and libc.test.src.stdlib.qsort_r_test).

I also wrote a small test program building with -DLIBC_QSORT_IMPL=LIBC_QSORT_HEAP_SORT to measure both the number of comparisons and execution time when sorting 100000 random strings over 50 iterations:
```
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define N 100000
#define ITERS 50

static uint64_t cmp_cnt;

static int cmp_str(const void *a, const void *b) {
  cmp_cnt++;
  return strcmp(*(const char *const *)a, *(const char *const *)b);
}

int main(void) {
  char **orig = malloc(N * sizeof(char *));
  char **arr = malloc(N * sizeof(char *));
  struct timespec t0, t1;
  double total_sec = 0.0;

  srand(42);
  for (size_t i = 0; i < N; i++) {
    orig[i] = malloc(32);
    snprintf(orig[i], 32, "prefix_string_%010d", rand());
  }

  cmp_cnt = 0;
  for (int it = 0; it < ITERS; it++) {
    memcpy(arr, orig, N * sizeof(char *));
    clock_gettime(CLOCK_MONOTONIC, &t0);
    qsort(arr, N, sizeof(char *), cmp_str);
    clock_gettime(CLOCK_MONOTONIC, &t1);
    total_sec += (t1.tv_sec - t0.tv_sec) + (t1.tv_nsec - t0.tv_nsec) * 1e-9;
  }

  printf("comparisons per run: %lu, avg time: %.3f ms\n",
         cmp_cnt / ITERS, (total_sec * 1e3) / ITERS);

  for (size_t i = 0; i < N; i++)
    free(orig[i]);
  free(orig);
  free(arr);
  return 0;
}
```
Results on x86-64:
- Before: comparisons per run: 3019211, avg time: 50.570 ms
- After: comparisons per run: 1699624, avg time: 35.989 ms (~43.7% fewer comparisons, ~28.8% faster)

https://github.com/llvm/llvm-project/pull/232602


More information about the libc-commits mailing list