summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eio.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/eio.c b/eio.c
index 9a41023..f44480c 100644
--- a/eio.c
+++ b/eio.c
@@ -1004,54 +1004,59 @@ eio_dent_cmp (const eio_dirent *a, const eio_dirent *b)
static void
eio_dent_sort (eio_dirent *dents, int size)
{
- /* should be good for 2**31 entries */
- struct rng { int l, r; } rng [32];
int i, j;
- i = 0;
- rng[0].l = 0;
- rng[0].r = size;
-
- while (expect_true (i >= 0))
+ if (size > EIO_QSORT_CUTOFF * 3) /* skip quicksort for small directories */
{
- int L = rng [i].l;
- int R = rng [i].r - 1;
+ /* first, use quicksort */
+ /* should be good for 2**31 entries */
+ struct rng { int l, r; } rng [32];
+
+ i = 0;
+ rng[0].l = 0;
+ rng[0].r = size;
- if (expect_false (L + EIO_QSORT_CUTOFF < R))
+ while (expect_true (i >= 0))
{
- eio_dirent piv = dents [L];
+ int L = rng [i].l;
+ int R = rng [i].r - 1;
- while (L < R)
+ if (expect_false (L + EIO_QSORT_CUTOFF < R))
{
- while (eio_dent_cmp (&dents [R], &piv) >= 0 && L < R)
- --R;
+ eio_dirent piv = dents [L];
- if (L < R)
- dents [L++] = dents [R];
+ while (L < R)
+ {
+ while (eio_dent_cmp (&dents [R], &piv) >= 0 && L < R)
+ --R;
- while (eio_dent_cmp (&dents [L], &piv) <= 0 && L < R)
- ++L;
+ if (L < R)
+ dents [L++] = dents [R];
- if (L < R)
- dents [R--] = dents [L];
- }
+ while (eio_dent_cmp (&dents [L], &piv) <= 0 && L < R)
+ ++L;
- dents [L] = piv;
+ if (L < R)
+ dents [R--] = dents [L];
+ }
- ++i;
- rng [i].l = L + 1;
- rng [i].r = rng [i - 1].r;
- rng [i - 1].r = L;
+ dents [L] = piv;
- if (rng [i].r - rng [i].l > rng [i - 1].r - rng [i - 1].l)
- {
- struct rng t;
+ ++i;
+ rng [i].l = L + 1;
+ rng [i].r = rng [i - 1].r;
+ rng [i - 1].r = L;
- t = rng [i]; rng [i] = rng [i - 1]; rng [i - 1] = t;
+ if (rng [i].r - rng [i].l > rng [i - 1].r - rng [i - 1].l)
+ {
+ struct rng t;
+
+ t = rng [i]; rng [i] = rng [i - 1]; rng [i - 1] = t;
+ }
}
+ else
+ --i;
}
- else
- --i;
}
/* use a simple insertion sort at the end */