]> mj.ucw.cz Git - libucw.git/blobdiff - lib/sorter/s-internal.h
Merge with git+ssh://git.ucw.cz/projects/sherlock/GIT/sherlock.git
[libucw.git] / lib / sorter / s-internal.h
index 765ed4b9892806855c0d0228261fd61fde038137..8cb869fcee02c6259078a0f747420185c83fd861 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"
 
 /*
@@ -90,7 +115,7 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
 #ifdef SORT_VAR_DATA
   if (sizeof(key) + 2*CPU_PAGE_SIZE + SORT_DATA_SIZE(key) + P(internal_workspace)(&key) > bufsize)
     {
 #ifdef SORT_VAR_DATA
   if (sizeof(key) + 2*CPU_PAGE_SIZE + SORT_DATA_SIZE(key) + P(internal_workspace)(&key) > bufsize)
     {
-      SORT_XTRACE(3, "s-internal: Generating a giant run");
+      SORT_XTRACE(4, "s-internal: Generating a giant run");
       struct fastbuf *out = sbuck_write(bout);
       P(copy_data)(&key, in, out);
       bout->runs++;
       struct fastbuf *out = sbuck_write(bout);
       P(copy_data)(&key, in, out);
       bout->runs++;
@@ -98,7 +123,7 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
     }
 #endif
 
     }
 #endif
 
-  SORT_XTRACE(4, "s-internal: Reading");
+  SORT_XTRACE(5, "s-internal: Reading");
   P(internal_item_t) *item_array = ctx->big_buf, *item = item_array, *last_item;
   byte *end = (byte *) ctx->big_buf + bufsize;
   size_t remains = bufsize - CPU_PAGE_SIZE;
   P(internal_item_t) *item_array = ctx->big_buf, *item = item_array, *last_item;
   byte *end = (byte *) ctx->big_buf + bufsize;
   size_t remains = bufsize - CPU_PAGE_SIZE;
@@ -112,7 +137,7 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
 #endif
       uns dsize = SORT_DATA_SIZE(key);
       uns recsize = ALIGN_TO(ksize_aligned + dsize, CPU_STRUCT_ALIGN);
 #endif
       uns dsize = SORT_DATA_SIZE(key);
       uns recsize = ALIGN_TO(ksize_aligned + dsize, CPU_STRUCT_ALIGN);
-      size_t totalsize = recsize + sizeof(P(internal_item_t) *) + P(internal_workspace)(&key);
+      size_t totalsize = recsize + sizeof(P(internal_item_t)) + P(internal_workspace)(&key);
       if (unlikely(totalsize > remains
 #ifdef CPU_64BIT_POINTERS
                   || item >= item_array + ~0U          // The number of items must fit in an uns
       if (unlikely(totalsize > remains
 #ifdef CPU_64BIT_POINTERS
                   || item >= item_array + ~0U          // The number of items must fit in an uns
@@ -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));
@@ -137,23 +165,24 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
 
   uns count = last_item - item_array;
   void *workspace UNUSED = ALIGN_PTR(last_item, CPU_PAGE_SIZE);
 
   uns count = last_item - item_array;
   void *workspace UNUSED = ALIGN_PTR(last_item, CPU_PAGE_SIZE);
-  SORT_XTRACE(3, "s-internal: Read %u items (%s items, %s workspace, %s data)",
+  SORT_XTRACE(4, "s-internal: Read %u items (%s items, %s workspace, %s data)",
        count,
        stk_fsize((byte*)last_item - (byte*)item_array),
        stk_fsize(end - (byte*)last_item - remains),
        stk_fsize((byte*)ctx->big_buf + bufsize - end));
   timestamp_t timer;
   init_timer(&timer);
        count,
        stk_fsize((byte*)last_item - (byte*)item_array),
        stk_fsize(end - (byte*)last_item - remains),
        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
     );
 #endif
     );
+  if ((void *)item_array != ctx->big_buf)
+    workspace = ctx->big_buf;
+  last_item = item_array + count;
   ctx->total_int_time += get_timer(&timer);
 
   ctx->total_int_time += get_timer(&timer);
 
-  SORT_XTRACE(4, "s-internal: Writing");
+  SORT_XTRACE(5, "s-internal: Writing");
   if (!ctx->more_keys)
     bout = bout_only;
   struct fastbuf *out = sbuck_write(bout);
   if (!ctx->more_keys)
     bout = bout_only;
   struct fastbuf *out = sbuck_write(bout);
@@ -191,7 +220,7 @@ static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct
 #endif
     }
 #ifdef SORT_UNIFY
 #endif
     }
 #ifdef SORT_UNIFY
-  SORT_XTRACE(3, "Merging reduced %u records", merged);
+  SORT_XTRACE(4, "Merging reduced %u records", merged);
 #endif
 
   return ctx->more_keys;
 #endif
 
   return ctx->more_keys;
@@ -200,15 +229,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