]> mj.ucw.cz Git - libucw.git/blobdiff - lib/sorter/s-internal.h
Made radix-sorting threshold configurable and let radix-tune-bits
[libucw.git] / lib / sorter / s-internal.h
index 765ed4b9892806855c0d0228261fd61fde038137..ef2da2402958cfa62bfdac3a69d575390ce7e0a8 100644 (file)
@@ -9,14 +9,39 @@
 
 #include "lib/stkstring.h"
 
 
 #include "lib/stkstring.h"
 
+#ifdef SORT_INTERNAL_RADIX
+/* Keep copies of the items' hashes to save cache misses */
+#define SORT_COPY_HASH
+#endif
+
 typedef struct {
   P(key) *key;
 typedef struct {
   P(key) *key;
-  // FIXME: Add the hash here to save cache misses
+#ifdef SORT_COPY_HASH
+  P(hash_t) hash;
+#endif
 } P(internal_item_t);
 
 #define ASORT_PREFIX(x) SORT_PREFIX(array_##x)
 #define ASORT_KEY_TYPE P(internal_item_t)
 } P(internal_item_t);
 
 #define ASORT_PREFIX(x) SORT_PREFIX(array_##x)
 #define ASORT_KEY_TYPE P(internal_item_t)
-#define ASORT_LT(x,y) (P(compare)((x).key, (y).key) < 0)
+#ifdef SORT_COPY_HASH
+#  ifdef SORT_INT
+#    define ASORT_LT(x,y) ((x).hash < (y).hash)                // In this mode, the hash is the value
+#  else
+#    define ASORT_LT(x,y) ((x).hash < (y).hash || (x).hash == (y).hash && P(compare)((x).key, (y).key) < 0)
+#  endif
+#else
+#  define ASORT_LT(x,y) (P(compare)((x).key, (y).key) < 0)
+#endif
+#ifdef SORT_INTERNAL_RADIX
+#    ifdef SORT_COPY_HASH
+#      define ASORT_HASH(x) (x).hash
+#    else
+#      define ASORT_HASH(x) P(hash)((x).key)
+#    endif
+#    ifdef SORT_LONG_HASH
+#      define ASORT_LONG_HASH
+#    endif
+#endif
 #include "lib/sorter/array.h"
 
 /*
 #include "lib/sorter/array.h"
 
 /*
@@ -130,6 +155,9 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
       breadb(in, end + ksize_aligned, dsize);
 #endif
       item->key = (P(key)*) end;
       breadb(in, end + ksize_aligned, dsize);
 #endif
       item->key = (P(key)*) end;
+#ifdef SORT_COPY_HASH
+      item->hash = P(hash)(item->key);
+#endif
       item++;
     }
   while (P(read_key)(in, &key));
       item++;
     }
   while (P(read_key)(in, &key));
@@ -144,11 +172,9 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
        stk_fsize((byte*)ctx->big_buf + bufsize - end));
   timestamp_t timer;
   init_timer(&timer);
        stk_fsize((byte*)ctx->big_buf + bufsize - end));
   timestamp_t timer;
   init_timer(&timer);
-  item_array = P(array_sort)(item_array, count,
+  item_array = P(array_sort)(item_array, count
 #ifdef SORT_INTERNAL_RADIX
 #ifdef SORT_INTERNAL_RADIX
-    workspace, bin->hash_bits
-#else
-    NULL, 0
+    , workspace, bin->hash_bits
 #endif
     );
   ctx->total_int_time += get_timer(&timer);
 #endif
     );
   ctx->total_int_time += get_timer(&timer);
@@ -200,15 +226,24 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
 static u64
 P(internal_estimate)(struct sort_context *ctx, struct sort_bucket *b UNUSED)
 {
 static u64
 P(internal_estimate)(struct sort_context *ctx, struct sort_bucket *b UNUSED)
 {
+  // Most of this is just wild guesses
 #ifdef SORT_VAR_KEY
 #ifdef SORT_VAR_KEY
-  uns avg = ALIGN_TO(sizeof(P(key))/4, CPU_STRUCT_ALIGN);      // Wild guess...
+  uns avg = ALIGN_TO(sizeof(P(key))/4, CPU_STRUCT_ALIGN);
 #else
   uns avg = ALIGN_TO(sizeof(P(key)), CPU_STRUCT_ALIGN);
 #endif
 #else
   uns avg = ALIGN_TO(sizeof(P(key)), CPU_STRUCT_ALIGN);
 #endif
-  // We ignore the data part of records, it probably won't make the estimate much worse
-  size_t bufsize = ctx->big_buf_size;
-#ifdef SORT_UNIFY_WORKSPACE            // FIXME: Or if radix-sorting
-  bufsize /= 2;
+  uns ws = 0;
+#ifdef SORT_UNIFY
+  ws += sizeof(void *);
+#endif
+#ifdef SORT_UNIFY_WORKSPACE
+  ws += avg;
 #endif
 #endif
-  return (bufsize / (avg + sizeof(P(internal_item_t))) * avg);
+#ifdef SORT_INTERNAL_RADIX
+  ws = MAX(ws, sizeof(P(internal_item_t)));
+#endif
+  // We ignore the data part of records, it probably won't make the estimate much worse
+  return (ctx->big_buf_size / (avg + ws + sizeof(P(internal_item_t))) * avg);
 }
 }
+
+#undef SORT_COPY_HASH