/* * UCW Library -- Universal Sorter: Fixed-Size Internal Sorting Module * * (c) 2007 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. */ #include #define ASORT_PREFIX(x) SORT_PREFIX(array_##x) #define ASORT_KEY_TYPE P(key) #define ASORT_LT(x,y) (P(compare)(&(x), &(y)) < 0) #ifdef SORT_INTERNAL_RADIX # define ASORT_HASH(x) P(hash)(&(x)) # ifdef SORT_LONG_HASH # define ASORT_LONG_HASH # endif #endif #include /* * 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 uint 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 uint } 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; uint maxkeys = P(internal_num_keys)(ctx); SORT_XTRACE(5, "s-fixint: Reading (maxkeys=%u, hash_bits=%d)", maxkeys, bin->hash_bits); uint 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(4, "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 ); if ((void *)buf != ctx->big_buf) workspace = ctx->big_buf; ctx->total_int_time += get_timer(&timer); SORT_XTRACE(5, "s-fixint: Writing"); if (n < maxkeys) bout = bout_only; struct fastbuf *out = sbuck_write(bout); bout->runs++; uint merged UNUSED = 0; for (uint i=0; i