]> git.sur5r.net Git - openldap/commitdiff
Use quicksort instead of heapsort for hdb_idl_sort
authorHoward Chu <hyc@openldap.org>
Mon, 12 Sep 2005 03:54:52 +0000 (03:54 +0000)
committerHoward Chu <hyc@openldap.org>
Mon, 12 Sep 2005 03:54:52 +0000 (03:54 +0000)
servers/slapd/back-bdb/idl.c
servers/slapd/back-bdb/idl.h

index 5c5e0ef304eb3524127699796d603ddf3883f2d5..e8d6546ff0c9996a7e8cb7f15beb99c079193223 100644 (file)
@@ -1297,43 +1297,71 @@ int bdb_idl_append( ID *a, ID *b )
        
 }
 
-/* Sort an IDL using HeapSort */
-static void
-siftDown(ID *ids, int root, int bottom)
-{
-       int child;
-       ID temp;
-
-       temp = ids[root];
-       while ((child=root*2) <= bottom) {
-               if (child < bottom && ids[child] < ids[child + 1])
-                       child++;
+/* Quicksort + Insertion sort for small arrays */
 
-               if (temp >= ids[child])
-                       break;
-               ids[root] = ids[child];
-               root = child;
-       }
-       ids[root] = temp;
-}
+#define SMALL  8
+#define        SWAP(a,b)       a^=b;b^=a;a^=b  /* Swap integers without temp var */
 
 void
 bdb_idl_sort( ID *ids )
 {
-       int i;
-       ID temp;
+       int istack[BDB_IDL_LOGN*4];
+       int i,j,k,l,ir,jstack;
+       ID a;
 
        if ( BDB_IDL_IS_RANGE( ids ))
                return;
 
-       for (i = ids[0] / 2; i >= 1; i--)
-               siftDown(ids, i, ids[0]);
-
-       for (i = ids[0]; i > 1; i--)
-       {
-               temp = ids[i];
-               ids[i] = ids[1];
-               ids[1] = temp;
-               siftDown(ids, 1, i-1);
+       ir = ids[0];
+       l = 1;
+       jstack = 0;
+       for(;;) {
+               if (ir - l < SMALL) {   /* Insertion sort */
+                       for (j=l+1;j<=ir;j++) {
+                               a = ids[j];
+                               for (i=j-1;i>=1;i--) {
+                                       if (ids[i] <= a) break;
+                                       ids[i+1] = ids[i];
+                               }
+                               ids[i+1] = a;
+                       }
+                       if (jstack == 0) break;
+                       ir = istack[jstack--];
+                       l = istack[jstack--];
+               } else {
+                       k = (l + ir) >> 1;      /* Choose median of left, center, right */
+                       SWAP(ids[k], ids[l+1]);
+                       if (ids[l] > ids[ir]) {
+                               SWAP(ids[l], ids[ir]);
+                       }
+                       if (ids[l+1] > ids[ir]) {
+                               SWAP(ids[l+1], ids[ir]);
+                       }
+                       if (ids[l] > ids[l+1]) {
+                               SWAP(ids[l], ids[l+1]);
+                       }
+                       i = l+1;
+                       j = ir;
+                       a = ids[l+1];
+                       for(;;) {
+                               do i++; while(ids[i] < a);
+                               do j--; while(ids[j] > a);
+                               if (j < i) break;
+                               SWAP(ids[i],ids[j]);
+                       }
+                       ids[l+1] = ids[j];
+                       ids[j] = a;
+                       jstack += 2;
+                       assert(jstack <= BDB_IDL_LOGN*4);
+                       if (ir-i+1 >= j-1) {
+                               istack[jstack] = ir;
+                               istack[jstack-1] = i;
+                               ir = j-1;
+                       } else {
+                               istack[jstack] = j-1;
+                               istack[jstack-1] = l;
+                               l = i;
+                       }
+               }
        }
 }
index 357c6539bdf62ce9a5eff51f7623ea8653b6e98d..29fcc83b0bca4cc2ca0e78e79dfe84c21049c14c 100644 (file)
@@ -20,8 +20,9 @@
 /* IDL sizes - likely should be even bigger
  *   limiting factors: sizeof(ID), thread stack size
  */
-#define BDB_IDL_DB_SIZE                (1<<16) /* 64K IDL on disk */
-#define BDB_IDL_UM_SIZE                (1<<17) /* 128K IDL in memory */
+#define        BDB_IDL_LOGN    16      /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
+#define BDB_IDL_DB_SIZE                (1<<BDB_IDL_LOGN)
+#define BDB_IDL_UM_SIZE                (1<<(BDB_IDL_LOGN+1))
 #define BDB_IDL_UM_SIZEOF      (BDB_IDL_UM_SIZE * sizeof(ID))
 
 #define BDB_IDL_DB_MAX         (BDB_IDL_DB_SIZE-1)