X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fsorter%2Fgovern.c;h=43b1668846fb975c1fb06fdfe415bb38df328586;hb=6bd2ff95b10c8c409eb178684294f1d17d79265b;hp=f761eb7df9e9ed23e104b655f5eaefd499d4a0b5;hpb=ff6fce257ce09477b27d9cd9e624ce0692e536b1;p=libucw.git diff --git a/lib/sorter/govern.c b/lib/sorter/govern.c index f761eb7d..43b16688 100644 --- a/lib/sorter/govern.c +++ b/lib/sorter/govern.c @@ -48,9 +48,14 @@ sorter_presort(struct sort_context *ctx, struct sort_bucket *in, struct sort_buc sorter_alloc_buf(ctx); if (in->flags & SBF_CUSTOM_PRESORT) { + /* + * The trick with automatic joining, which we use for the normal presorter, + * is not necessary with the custom presorter, because the custom presorter + * is never called in the middle of the sorted data. + */ struct fastbuf *f = sbuck_write(out); out->runs++; - return ctx->custom_presort(f, ctx->big_buf, ctx->big_buf_size); // FIXME: out_only optimization? + return ctx->custom_presort(f, ctx->big_buf, ctx->big_buf_size); } return ctx->internal_sort(ctx, in, out, out_only); } @@ -100,7 +105,7 @@ sorter_join(struct sort_bucket *b) { // The final bucket doesn't have any file associated yet, so replace // it with the new bucket. - SORT_XTRACE(2, "Replaced final bucket"); + SORT_XTRACE(3, "Replaced final bucket"); b->flags |= SBF_FINAL; sbuck_drop(join); } @@ -131,7 +136,7 @@ sorter_twoway(struct sort_context *ctx, struct sort_bucket *b) { sorter_stop_timer(ctx, &ctx->total_pre_time); sh_off_t size = sbuck_ins_or_join(ins[0], list_pos, join, join_size); - SORT_XTRACE(((b->flags & SBF_SOURCE) ? 1 : 2), "Sorted in memory (%s, %dMB/s)", stk_fsize(size), sorter_speed(ctx, size)); + SORT_XTRACE(((b->flags & SBF_SOURCE) ? 1 : 3), "Sorted in memory (%s, %dMB/s)", stk_fsize(size), sorter_speed(ctx, size)); sbuck_drop(b); return; } @@ -196,7 +201,7 @@ sorter_multiway(struct sort_context *ctx, struct sort_bucket *b) cnode *list_pos = b->n.prev; sh_off_t join_size; struct sort_bucket *join = sbuck_join_to(b, &join_size); - uns trace_level = (b->flags & SBF_SOURCE) ? 1 : 2; + uns trace_level = (b->flags & SBF_SOURCE) ? 1 : 3; clist_init(&parts); ASSERT(!(sorter_debug & SORT_DEBUG_NO_PRESORT)); @@ -226,7 +231,7 @@ sorter_multiway(struct sort_context *ctx, struct sort_bucket *b) if (part_cnt <= 1) { - sh_off_t size = sbuck_ins_or_join(clist_head(&parts), list_pos, join, join_size); + sh_off_t size = sbuck_ins_or_join(clist_head(&parts), list_pos, (part_cnt ? NULL : join), join_size); SORT_XTRACE(trace_level, "Sorted in memory (%s, %dMB/s)", stk_fsize(size), sorter_speed(ctx, size)); return; } @@ -235,7 +240,7 @@ sorter_multiway(struct sort_context *ctx, struct sort_bucket *b) uns max_ways = 1 << sorter_max_multiway_bits; struct sort_bucket *ways[max_ways+1]; - SORT_XTRACE(2, "Starting up to %d-way merge", max_ways); + SORT_XTRACE(3, "Starting up to %d-way merge", max_ways); for (;;) { uns n = 0; @@ -278,8 +283,11 @@ sorter_multiway(struct sort_context *ctx, struct sort_bucket *b) static void sorter_radix(struct sort_context *ctx, struct sort_bucket *b, uns bits) { + // Add more bits if requested and allowed. + bits = MIN(bits + sorter_add_radix_bits, sorter_max_radix_bits); + uns nbuck = 1 << bits; - SORT_XTRACE(2, "Running radix split on %s with hash %d bits of %d (expecting %s buckets)", + SORT_XTRACE(3, "Running radix split on %s with hash %d bits of %d (expecting %s buckets)", F_BSIZE(b), bits, b->hash_bits, stk_fsize(sbuck_size(b) / nbuck)); sorter_free_buf(ctx); sorter_start_timer(ctx); @@ -317,7 +325,7 @@ sorter_decide(struct sort_context *ctx, struct sort_bucket *b) // Drop empty buckets if (!sbuck_have(b)) { - SORT_XTRACE(3, "Dropping empty bucket"); + SORT_XTRACE(4, "Dropping empty bucket"); sbuck_drop(b); return; } @@ -325,7 +333,7 @@ sorter_decide(struct sort_context *ctx, struct sort_bucket *b) // How many bits of bucket size we have to reduce before it fits in the RAM? // (this is insanely large if the input size is unknown, but it serves our purpose) u64 insize = sbuck_size(b); - u64 mem = ctx->internal_estimate(ctx, b) * 0.8; // FIXME: Magical factor for various non-uniformities + u64 mem = ctx->internal_estimate(ctx, b) * 0.8; // Magical factor accounting for various non-uniformities uns bits = 0; while ((insize >> bits) > mem) bits++; @@ -357,7 +365,7 @@ sorter_decide(struct sort_context *ctx, struct sort_bucket *b) multiway_bits = 0; } - SORT_XTRACE(2, "Decisions: size=%s max=%s runs=%d bits=%d hash=%d -> radix=%d multi=%d", + SORT_XTRACE(3, "Decisions: size=%s max=%s runs=%d bits=%d hash=%d -> radix=%d multi=%d", stk_fsize(insize), stk_fsize(mem), b->runs, bits, b->hash_bits, radix_bits, multiway_bits); @@ -391,6 +399,7 @@ sorter_run(struct sort_context *ctx) ctx->pool = mp_new(4096); clist_init(&ctx->bucket_list); sorter_prepare_buf(ctx); + asort_start_threads(0); // Create bucket containing the source struct sort_bucket *bin = sbuck_new(ctx); @@ -404,6 +413,7 @@ sorter_run(struct sort_context *ctx) bin->hash_bits = ctx->hash_bits; clist_add_tail(&ctx->bucket_list, &bin->n); SORT_XTRACE(2, "Input size: %s, %d hash bits", F_BSIZE(bin), bin->hash_bits); + ctx->fb_params = (bin->size < sorter_small_input) ? &sorter_small_fb_params : &sorter_fb_params; // Create bucket for the output struct sort_bucket *bout = sbuck_new(ctx); @@ -419,10 +429,12 @@ sorter_run(struct sort_context *ctx) while (bout = clist_head(&ctx->bucket_list), b = clist_next(&ctx->bucket_list, &bout->n)) sorter_decide(ctx, b); + asort_stop_threads(); sorter_free_buf(ctx); sbuck_write(bout); // Force empty bucket to a file SORT_XTRACE(2, "Final size: %s", F_BSIZE(bout)); SORT_XTRACE(2, "Final timings: %.3fs external sorting, %.3fs presorting, %.3fs internal sorting", ctx->total_ext_time/1000., ctx->total_pre_time/1000., ctx->total_int_time/1000.); ctx->out_fb = sbuck_read(bout); + mp_delete(ctx->pool); }