]> mj.ucw.cz Git - libucw.git/blobdiff - lib/sorter/s-fixint.h
Made radix-sorting threshold configurable and let radix-tune-bits
[libucw.git] / lib / sorter / s-fixint.h
index bb555fb90c3b9d1e858e688a9231ad59a6ba29a2..9787a682010b1a8c88659acd4eb4543a6daca8bc 100644 (file)
@@ -7,25 +7,47 @@
  *     of the GNU Lesser General Public License.
  */
 
  *     of the GNU Lesser General Public License.
  */
 
+#include "lib/stkstring.h"
+
 #define ASORT_PREFIX(x) SORT_PREFIX(array_##x)
 #define ASORT_KEY_TYPE P(key)
 #define ASORT_PREFIX(x) SORT_PREFIX(array_##x)
 #define ASORT_KEY_TYPE P(key)
-#define ASORT_ELT(i) ary[i]
 #define ASORT_LT(x,y) (P(compare)(&(x), &(y)) < 0)
 #define ASORT_LT(x,y) (P(compare)(&(x), &(y)) < 0)
-#define ASORT_EXTRA_ARGS , P(key) *ary
-#include "lib/arraysort.h"
+#ifdef SORT_INTERNAL_RADIX
+#  define ASORT_HASH(x) P(hash)(&(x))
+#    ifdef SORT_LONG_HASH
+#      define ASORT_LONG_HASH
+#    endif
+#endif
+#include "lib/sorter/array.h"
+
+/*
+ *  This is a more efficient implementation of the internal sorter,
+ *  which runs under the following assumptions:
+ *
+ *     - the keys have fixed (and small) size
+ *     - no data are present after the key
+ *     - unification does not require any workspace
+ */
 
 
-static int P(internal_num_keys)(struct sort_context *ctx)
+static size_t P(internal_workspace)(void)
 {
 {
-  size_t bufsize = ctx->big_buf_half_size;
+  size_t workspace = 0;
 #ifdef SORT_UNIFY
 #ifdef SORT_UNIFY
-  // When we promise unification, we have to reduce the number of records
-  // to be sure that both pointers and merged records fit in the 2nd half
-  // of the big_buf. So we eat as much memory as s-internal.h, but still
-  // we are faster.
-  u64 maxkeys = bufsize / (sizeof(P(key)) + sizeof(void *));
-#else
-  u64 maxkeys = bufsize / sizeof(P(key));
+  workspace = sizeof(P(key) *);
 #endif
 #endif
+#ifdef SORT_INTERNAL_RADIX
+  workspace = MAX(workspace, sizeof(P(key)));
+#endif
+  return workspace;
+}
+
+static uns P(internal_num_keys)(struct sort_context *ctx)
+{
+  size_t bufsize = ctx->big_buf_size;
+  size_t workspace = P(internal_workspace)();
+  if (workspace)
+    bufsize -= CPU_PAGE_SIZE;
+  u64 maxkeys = bufsize / (sizeof(P(key)) + workspace);
   return MIN(maxkeys, ~0U);                                    // The number of records must fit in uns
 }
 
   return MIN(maxkeys, ~0U);                                    // The number of records must fit in uns
 }
 
@@ -36,18 +58,31 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
   P(key) *buf = ctx->big_buf;
   uns maxkeys = P(internal_num_keys)(ctx);
 
   P(key) *buf = ctx->big_buf;
   uns maxkeys = P(internal_num_keys)(ctx);
 
-  SORT_XTRACE(3, "s-fixint: Reading (maxkeys=%u)", maxkeys);
+  SORT_XTRACE(4, "s-fixint: Reading (maxkeys=%u, hash_bits=%d)", maxkeys, bin->hash_bits);
   uns n = 0;
   while (n < maxkeys && P(read_key)(in, &buf[n]))
     n++;
   if (!n)
     return 0;
   uns n = 0;
   while (n < maxkeys && P(read_key)(in, &buf[n]))
     n++;
   if (!n)
     return 0;
+  void *workspace UNUSED = ALIGN_PTR(&buf[n], CPU_PAGE_SIZE);
 
 
-  SORT_XTRACE(3, "s-fixint: Sorting %u items", n);
-  P(array_sort)(n, buf);
+  SORT_XTRACE(3, "s-fixint: Sorting %u items (%s items, %s workspace)",
+       n,
+       stk_fsize(n * sizeof(P(key))),
+       stk_fsize(n * P(internal_workspace)()));
+  timestamp_t timer;
+  init_timer(&timer);
+  buf = P(array_sort)(buf, n
+#ifdef SORT_INTERNAL_RADIX
+    , workspace, bin->hash_bits
+#endif
+    );
+  ctx->total_int_time += get_timer(&timer);
 
 
-  SORT_XTRACE(3, "s-fixint: Writing");
-  struct fastbuf *out = sbuck_write((n < maxkeys) ? bout_only : bout);
+  SORT_XTRACE(4, "s-fixint: Writing");
+  if (n < maxkeys)
+    bout = bout_only;
+  struct fastbuf *out = sbuck_write(bout);
   bout->runs++;
   uns merged UNUSED = 0;
   for (uns i=0; i<n; i++)
   bout->runs++;
   uns merged UNUSED = 0;
   for (uns i=0; i<n; i++)
@@ -55,7 +90,7 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
 #ifdef SORT_UNIFY
       if (i < n-1 && !P(compare)(&buf[i], &buf[i+1]))
        {
 #ifdef SORT_UNIFY
       if (i < n-1 && !P(compare)(&buf[i], &buf[i+1]))
        {
-         P(key) **keys = ctx->big_buf_half;
+         P(key) **keys = workspace;
          uns n = 2;
          keys[0] = &buf[i];
          keys[1] = &buf[i+1];
          uns n = 2;
          keys[0] = &buf[i];
          keys[1] = &buf[i+1];
@@ -64,7 +99,7 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
              keys[n] = &buf[i+n];
              n++;
            }
              keys[n] = &buf[i+n];
              n++;
            }
-         P(write_merged)(out, keys, NULL, n, keys+n);
+         P(write_merged)(out, keys, NULL, n, NULL);
          merged += n - 1;
          i += n - 1;
          continue;
          merged += n - 1;
          i += n - 1;
          continue;