X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fsorter%2Fs-fixint.h;h=9787a682010b1a8c88659acd4eb4543a6daca8bc;hb=1a3cd3005f2a5cda8dbdaaf8f153ae5703845876;hp=9148509360f878ef73a2f7e31eacbdbc8519df1c;hpb=264b43467496dd515d2c432d5f95201ce10600ce;p=libucw.git diff --git a/lib/sorter/s-fixint.h b/lib/sorter/s-fixint.h index 91485093..9787a682 100644 --- a/lib/sorter/s-fixint.h +++ b/lib/sorter/s-fixint.h @@ -7,34 +7,82 @@ * 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_ELT(i) ary[i] #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 size_t P(internal_workspace)(void) +{ + size_t workspace = 0; +#ifdef SORT_UNIFY + workspace = sizeof(P(key) *); +#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 +} static int P(internal)(struct sort_context *ctx, struct sort_bucket *bin, struct sort_bucket *bout, struct sort_bucket *bout_only) { sorter_alloc_buf(ctx); struct fastbuf *in = sbuck_read(bin); P(key) *buf = ctx->big_buf; - size_t bufsize = ctx->big_buf_half_size; /* FIXME: In some cases, we can use the whole buffer */ -#ifdef CPU_64BIT_POINTERS - bufsize = MIN((u64)bufsize, (u64)~0U * sizeof(P(key))); // The number of records must fit in uns -#endif - uns maxkeys = bufsize / sizeof(P(key)); + 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; + 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; ibig_buf_half_size - 1; // -1 since if the buffer is full, we don't recognize EOF + return P(internal_num_keys)(ctx) * sizeof(P(key)) - 1; // -1 since if the buffer is full, we don't recognize EOF }