mirror of
https://github.com/isar/libmdbx.git
synced 2025-11-06 19:08:56 +08:00
mdbx: clean library core from using a float-point.
This commit is contained in:
155
src/chk.c
155
src/chk.c
@@ -196,6 +196,49 @@ __cold static MDBX_chk_line_t *chk_print_size(MDBX_chk_line_t *line, const char
|
||||
return line;
|
||||
}
|
||||
|
||||
__cold static MDBX_chk_line_t *chk_print_ratio(MDBX_chk_line_t *line, size_t numerator, size_t denominator,
|
||||
unsigned precision) {
|
||||
if (line) {
|
||||
ratio2digits_buffer_t buffer;
|
||||
line = chk_puts(line, ratio2digits(numerator, denominator, &buffer, precision));
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
__cold static MDBX_chk_line_t *chk_print_percent(MDBX_chk_line_t *line, const char *triplet, size_t value, size_t whole,
|
||||
const char *unit) {
|
||||
if (line) {
|
||||
const char *s1 = triplet;
|
||||
const char *s2 = s1 + strlen(s1) + 1;
|
||||
const char *s3 = s2 + strlen(s2) + 1;
|
||||
ratio2digits_buffer_t buffer;
|
||||
line = chk_print(line, "%s %" PRIuSIZE "%s%s (%s%%%s)%s", s1, value, unit, &"s"[*unit == 0 || value == 1],
|
||||
ratio2percent(value, whole, &buffer), s2, s3);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
__cold static MDBX_chk_line_t *chk_print_pages_percent(MDBX_chk_line_t *line, const char *triplet, size_t pages,
|
||||
size_t whole) {
|
||||
return chk_print_percent(line, triplet, pages, whole, " page");
|
||||
}
|
||||
|
||||
__cold static MDBX_chk_line_t *chk_print_bytes_percent(MDBX_chk_line_t *line, const char *triplet, size_t pages,
|
||||
size_t whole) {
|
||||
return chk_print_percent(line, triplet, pages, whole, " byte");
|
||||
}
|
||||
|
||||
__cold static MDBX_chk_line_t *chk_print_pages_percent_bb(MDBX_chk_line_t *line, const char *prefix, size_t pages,
|
||||
size_t backed, size_t boundary) {
|
||||
if (line) {
|
||||
ratio2digits_buffer_t buffer_backed, buffer_boundary;
|
||||
line =
|
||||
chk_print(line, "%s %" PRIuSIZE " page%s (%s%% of backed, %s%% of boundary)", prefix, pages, &"s"[pages == 1],
|
||||
ratio2percent(pages, backed, &buffer_backed), ratio2percent(pages, boundary, &buffer_boundary));
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
__cold static int chk_error_rc(MDBX_chk_scope_t *const scope, int err, const char *subj) {
|
||||
MDBX_chk_line_t *line = chk_line_begin(scope, MDBX_chk_error);
|
||||
if (line)
|
||||
@@ -964,13 +1007,11 @@ __cold static int chk_tree(MDBX_chk_scope_t *const scope) {
|
||||
tbl->pages.nested_leaf, tbl->pages.nested_subleaf);
|
||||
}
|
||||
|
||||
line = chk_line_feed(line);
|
||||
const size_t bytes = pgno2bytes(env, tbl->pages.all);
|
||||
line =
|
||||
chk_print(chk_line_feed(line),
|
||||
"page filling: subtotal %" PRIuSIZE " bytes (%.1f%%), payload %" PRIuSIZE
|
||||
" (%.1f%%), unused %" PRIuSIZE " (%.1f%%)",
|
||||
bytes, bytes * 100.0 / total_page_bytes, tbl->payload_bytes, tbl->payload_bytes * 100.0 / bytes,
|
||||
bytes - tbl->payload_bytes, (bytes - tbl->payload_bytes) * 100.0 / bytes);
|
||||
line = chk_print_bytes_percent(line, "page filling: subtotal\0\0", bytes, total_page_bytes);
|
||||
line = chk_print_percent(line, ", payload\0\0", tbl->payload_bytes, bytes, "");
|
||||
line = chk_print_percent(line, ", unused\0\0", bytes - tbl->payload_bytes, bytes, "");
|
||||
if (tbl->pages.empty)
|
||||
line = chk_print(line, ", %" PRIuSIZE " empty pages", tbl->pages.empty);
|
||||
if (tbl->lost_bytes)
|
||||
@@ -989,14 +1030,11 @@ __cold static int chk_tree(MDBX_chk_scope_t *const scope) {
|
||||
}
|
||||
|
||||
MDBX_chk_line_t *line = chk_line_begin(scope, MDBX_chk_resolution);
|
||||
line = chk_print(line,
|
||||
"summary: total %" PRIuSIZE " bytes, payload %" PRIuSIZE " (%.1f%%), unused %" PRIuSIZE " (%.1f%%),"
|
||||
" average fill %.1f%%",
|
||||
total_page_bytes, usr->result.total_payload_bytes,
|
||||
usr->result.total_payload_bytes * 100.0 / total_page_bytes,
|
||||
total_page_bytes - usr->result.total_payload_bytes,
|
||||
(total_page_bytes - usr->result.total_payload_bytes) * 100.0 / total_page_bytes,
|
||||
usr->result.total_payload_bytes * 100.0 / total_page_bytes);
|
||||
line = chk_print(line, "summary: total %" PRIuSIZE " bytes", total_page_bytes);
|
||||
line =
|
||||
chk_print_percent(line, ", payload\0 average density\0", usr->result.total_payload_bytes, total_page_bytes, "");
|
||||
line = chk_print_percent(line, ", unused\0 average sparsity\0", total_page_bytes - usr->result.total_payload_bytes,
|
||||
total_page_bytes, "");
|
||||
if (total.pages.empty)
|
||||
line = chk_print(line, ", %" PRIuSIZE " empty pages", total.pages.empty);
|
||||
if (total.lost_bytes)
|
||||
@@ -1292,8 +1330,9 @@ bailout:
|
||||
chk_line_feed(line);
|
||||
line = histogram_dist(line, &tbl->histogram.multival, "number of multi-values density", "single", false);
|
||||
chk_line_feed(line);
|
||||
line = chk_print(line, "number of keys %" PRIuSIZE ", average values per key %.1f",
|
||||
tbl->histogram.multival.count, record_count / (double)tbl->histogram.multival.count);
|
||||
line =
|
||||
chk_print(line, "number of keys %" PRIuSIZE ", average values per key ", tbl->histogram.multival.count);
|
||||
line = chk_print_ratio(line, record_count, tbl->histogram.multival.count, 1);
|
||||
}
|
||||
chk_line_end(line);
|
||||
}
|
||||
@@ -1449,8 +1488,8 @@ __cold static int env_chk(MDBX_chk_scope_t *const scope) {
|
||||
line = chk_puts(line, "is unavailable");
|
||||
chk_line_end(line);
|
||||
|
||||
line = chk_print_size(chk_line_begin(scope, MDBX_chk_verbose), "system io-block ", chk->envinfo.mi_sys_ioblk, ", ");
|
||||
line = chk_print_size(line, "unified page cache block ", chk->envinfo.mi_sys_upcblk, "");
|
||||
line = chk_print_size(chk_line_begin(scope, MDBX_chk_verbose), "system unified page cache block ",
|
||||
chk->envinfo.mi_sys_upcblk, "");
|
||||
chk_line_end(line);
|
||||
|
||||
env->dxb_mmap.filesize = chk->envinfo.mi_dxb_fsize;
|
||||
@@ -1532,9 +1571,18 @@ __cold static int env_chk(MDBX_chk_scope_t *const scope) {
|
||||
chk_line_end(chk_print(line, " > until it will be closed or reopened in read-write mode."));
|
||||
}
|
||||
#endif /* Windows || Debug */
|
||||
line = chk_print_size(chk_line_begin(scope, MDBX_chk_verbose), "space allocated for the dxb-file in a filesystem ",
|
||||
chk->envinfo.mi_dxb_fallocated, " ");
|
||||
line = chk_print(line, "%.2f%%", 100.0 * chk->envinfo.mi_dxb_fallocated / chk->envinfo.mi_geo.current);
|
||||
line = chk_print_size(chk_line_begin(scope, MDBX_chk_verbose), "filesystem: io-block ", chk->envinfo.mi_sys_ioblk,
|
||||
", space allocated for the dxb-file ");
|
||||
if (chk->envinfo.mi_dxb_fallocated == chk->envinfo.mi_geo.current) {
|
||||
line = chk_puts(line, "exactly");
|
||||
} else {
|
||||
line = chk_print_size(
|
||||
line, (chk->envinfo.mi_dxb_fallocated > chk->envinfo.mi_geo.current) ? "with excess " : "partially ",
|
||||
chk->envinfo.mi_dxb_fallocated, " ");
|
||||
ratio2digits_buffer_t buffer;
|
||||
line =
|
||||
chk_print(line, "%s%%", ratio2percent(chk->envinfo.mi_dxb_fallocated, chk->envinfo.mi_geo.current, &buffer));
|
||||
}
|
||||
chk_line_end(line);
|
||||
chk_verbose_meta(inner, 0);
|
||||
chk_verbose_meta(inner, 1);
|
||||
@@ -1652,69 +1700,50 @@ __cold static int env_chk(MDBX_chk_scope_t *const scope) {
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
err = chk_scope_begin(chk, 1, MDBX_chk_space, nullptr, nullptr, "Page allocation:");
|
||||
const double percent_boundary_reciprocal = 100.0 / txn->geo.upper;
|
||||
const double percent_backed_reciprocal = 100.0 / usr->result.backed_pages;
|
||||
const size_t backed = usr->result.backed_pages;
|
||||
const size_t boundary = txn->geo.upper;
|
||||
const size_t detained = usr->result.gc_pages - usr->result.reclaimable_pages;
|
||||
const size_t available2boundary = txn->geo.upper - usr->result.alloc_pages + usr->result.reclaimable_pages;
|
||||
const size_t available2backed = usr->result.backed_pages - usr->result.alloc_pages + usr->result.reclaimable_pages;
|
||||
const size_t remained2boundary = txn->geo.upper - usr->result.alloc_pages;
|
||||
const size_t remained2backed = usr->result.backed_pages - usr->result.alloc_pages;
|
||||
const size_t available2boundary = boundary - usr->result.alloc_pages + usr->result.reclaimable_pages;
|
||||
const size_t available2backed = backed - usr->result.alloc_pages + usr->result.reclaimable_pages;
|
||||
const size_t remained2boundary = boundary - usr->result.alloc_pages;
|
||||
const size_t remained2backed = backed - usr->result.alloc_pages;
|
||||
|
||||
const size_t used = (chk->flags & MDBX_CHK_SKIP_BTREE_TRAVERSAL) ? usr->result.alloc_pages - usr->result.gc_pages
|
||||
: usr->result.processed_pages;
|
||||
|
||||
line = chk_line_begin(usr->scope, MDBX_chk_info);
|
||||
line = chk_print(line,
|
||||
"backed by file: %" PRIuSIZE " pages (%.1f%%)"
|
||||
", %" PRIuSIZE " left to boundary (%.1f%%)",
|
||||
usr->result.backed_pages, usr->result.backed_pages * percent_boundary_reciprocal,
|
||||
txn->geo.upper - usr->result.backed_pages,
|
||||
(txn->geo.upper - usr->result.backed_pages) * percent_boundary_reciprocal);
|
||||
line = chk_print_pages_percent(line, "backed by file:\0 of boundary\0", backed, boundary);
|
||||
line = chk_print_pages_percent(line, ",\0\0 left to boundary", boundary - backed, boundary);
|
||||
line = chk_line_feed(line);
|
||||
|
||||
line = chk_print(line, "%s: %" PRIuSIZE " page(s), %.1f%% of backed, %.1f%% of boundary", "used", used,
|
||||
used * percent_backed_reciprocal, used * percent_boundary_reciprocal);
|
||||
line = chk_print_pages_percent_bb(line, "used:", used, backed, boundary);
|
||||
line = chk_line_feed(line);
|
||||
|
||||
line = chk_print(line, "%s: %" PRIuSIZE " page(s) (%.1f%%) of backed, %" PRIuSIZE " to boundary (%.1f%% of boundary)",
|
||||
"remained", remained2backed, remained2backed * percent_backed_reciprocal, remained2boundary,
|
||||
remained2boundary * percent_boundary_reciprocal);
|
||||
line = chk_print_pages_percent(line, "remained:\0\0 of backed", remained2backed, backed);
|
||||
line = chk_print_pages_percent(line, ", left\0\0 to boundary", remained2boundary, boundary);
|
||||
line = chk_line_feed(line);
|
||||
|
||||
line =
|
||||
chk_print(line,
|
||||
"reclaimable: %" PRIuSIZE " (%.1f%% of backed, %.1f%% of boundary)"
|
||||
", GC %" PRIuSIZE " (%.1f%% of backed, %.1f%% of boundary)",
|
||||
usr->result.reclaimable_pages, usr->result.reclaimable_pages * percent_backed_reciprocal,
|
||||
usr->result.reclaimable_pages * percent_boundary_reciprocal, usr->result.gc_pages,
|
||||
usr->result.gc_pages * percent_backed_reciprocal, usr->result.gc_pages * percent_boundary_reciprocal);
|
||||
line = chk_print_pages_percent_bb(line, "reclaimable:", usr->result.reclaimable_pages, backed, boundary);
|
||||
line = chk_print_pages_percent_bb(line, ", within GC", usr->result.gc_pages, backed, boundary);
|
||||
line = chk_line_feed(line);
|
||||
|
||||
line = chk_print(line,
|
||||
"detained by reader(s): %" PRIuSIZE " (%.1f%% of backed, %.1f%% of boundary)"
|
||||
", %u reader(s), lag %" PRIi64,
|
||||
detained, detained * percent_backed_reciprocal, detained * percent_boundary_reciprocal,
|
||||
chk->envinfo.mi_numreaders, chk->envinfo.mi_recent_txnid - chk->envinfo.mi_latter_reader_txnid);
|
||||
line = chk_print_pages_percent_bb(line, "detained by reader(s):", detained, backed, boundary);
|
||||
line = chk_print(line, ", %u reader(s), lag %" PRIi64, chk->envinfo.mi_numreaders,
|
||||
chk->envinfo.mi_recent_txnid - chk->envinfo.mi_latter_reader_txnid);
|
||||
line = chk_line_feed(line);
|
||||
|
||||
line = chk_print(line, "%s: %" PRIuSIZE " page(s), %.1f%% of backed, %.1f%% of boundary", "allocated",
|
||||
usr->result.alloc_pages, usr->result.alloc_pages * percent_backed_reciprocal,
|
||||
usr->result.alloc_pages * percent_boundary_reciprocal);
|
||||
line = chk_print_pages_percent_bb(line, "allocated:", usr->result.alloc_pages, backed, boundary);
|
||||
line = chk_line_feed(line);
|
||||
|
||||
line = chk_print(line, "%s: %" PRIuSIZE " page(s) (%.1f%%) of backed, %" PRIuSIZE " to boundary (%.1f%% of boundary)",
|
||||
"available", available2backed, available2backed * percent_backed_reciprocal, available2boundary,
|
||||
available2boundary * percent_boundary_reciprocal);
|
||||
line = chk_print_pages_percent(line, "available:\0 of backed\0", available2backed, backed);
|
||||
line = chk_print_pages_percent(line, ", left\0\0 to boundary", available2boundary, boundary);
|
||||
chk_line_end(line);
|
||||
|
||||
line = chk_line_begin(usr->scope, MDBX_chk_resolution);
|
||||
line = chk_print(line, "%s %" PRIaPGNO " pages", (txn->geo.upper == txn->geo.now) ? "total" : "upto", txn->geo.upper);
|
||||
line = chk_print(line, ", backed %" PRIuSIZE " (%.1f%%)", usr->result.backed_pages,
|
||||
usr->result.backed_pages * percent_boundary_reciprocal);
|
||||
line = chk_print(line, ", allocated %" PRIuSIZE " (%.1f%%)", usr->result.alloc_pages,
|
||||
usr->result.alloc_pages * percent_boundary_reciprocal);
|
||||
line = chk_print(line, ", available %" PRIuSIZE " (%.1f%%)", available2boundary,
|
||||
available2boundary * percent_boundary_reciprocal);
|
||||
line = chk_print(line, "%s %zu pages", (boundary == txn->geo.now) ? "total" : "upto", boundary);
|
||||
line = chk_print_pages_percent(line, ", backed\0\0", backed, boundary);
|
||||
line = chk_print_pages_percent(line, ", allocated\0\0", usr->result.alloc_pages, boundary);
|
||||
line = chk_print_pages_percent(line, ", available\0\0", available2boundary, boundary);
|
||||
chk_line_end(line);
|
||||
chk_scope_restore(scope, err);
|
||||
|
||||
|
||||
@@ -1290,9 +1290,12 @@ static int gc_fill_returned(MDBX_txn *txn, gcu_t *ctx) {
|
||||
rkl_iter_t iter = rkl_iterator(&txn->wr.gc.comeback, is_lifo(txn));
|
||||
size_t surplus = ctx->return_reserved_hi - amount, stored = 0;
|
||||
const uint64_t factor = ((uint64_t)surplus << 32) / ctx->return_reserved_hi;
|
||||
TRACE("%s: amount %zu, slots %zu, surplus %zu (%zu..%zu), factor %.6f (%" PRIu64 " >> 32, sharp %.12f)",
|
||||
dbg_prefix(ctx), amount, slots, surplus, ctx->return_reserved_lo, ctx->return_reserved_hi,
|
||||
factor / (double)UINT32_MAX, factor, surplus / (double)ctx->return_reserved_hi);
|
||||
ratio2digits_buffer_t factor_rough, factor_sharp;
|
||||
TRACE("%s: amount %zu, slots %zu, surplus %zu (%zu..%zu), factor %s (%" PRIu64 " >> 32, sharp %s)", dbg_prefix(ctx),
|
||||
amount, slots, surplus, ctx->return_reserved_lo, ctx->return_reserved_hi,
|
||||
ratio2digits(factor, UINT32_MAX, &factor_rough, 6), factor,
|
||||
ratio2digits(surplus, ctx->return_reserved_hi, &factor_sharp, 12));
|
||||
|
||||
do {
|
||||
const size_t left = amount - stored;
|
||||
tASSERT(txn, left > 0 && left <= amount);
|
||||
|
||||
49
src/utils.c
49
src/utils.c
@@ -41,3 +41,52 @@ MDBX_NOTHROW_CONST_FUNCTION uint64_t rrxmrrxmsx_0(uint64_t v) {
|
||||
v *= UINT64_C(0x9FB21C651E98DF25);
|
||||
return v ^ v >> 28;
|
||||
}
|
||||
|
||||
__cold char *ratio2digits(const uint64_t v, const uint64_t d, ratio2digits_buffer_t *const buffer, int precision) {
|
||||
assert(d > 0 && precision < 20);
|
||||
char *const dot = buffer->string + 21;
|
||||
uint64_t i = v / d, f = v % d, m = d;
|
||||
|
||||
char *tail = dot;
|
||||
bool carry = m - f < m / 2;
|
||||
if (precision > 0) {
|
||||
*tail = '.';
|
||||
do {
|
||||
while (unlikely(f > UINT64_MAX / 10)) {
|
||||
f >>= 1;
|
||||
m >>= 1;
|
||||
}
|
||||
f *= 10;
|
||||
assert(tail > buffer->string && tail < ARRAY_END(buffer->string) - 1);
|
||||
*++tail = '0' + (char)(f / m);
|
||||
f %= m;
|
||||
} while (--precision && tail < ARRAY_END(buffer->string) - 1);
|
||||
|
||||
carry = m - f < m / 2;
|
||||
for (char *scan = tail; carry && scan > dot; --scan)
|
||||
*scan = (carry = *scan == '9') ? '0' : *scan + 1;
|
||||
}
|
||||
assert(tail > buffer->string && tail < ARRAY_END(buffer->string) - 1);
|
||||
*++tail = '\0';
|
||||
|
||||
char *head = dot;
|
||||
i += carry;
|
||||
while (i > 9) {
|
||||
assert(head > buffer->string && head < ARRAY_END(buffer->string));
|
||||
*--head = '0' + (char)(i % 10);
|
||||
i /= 10;
|
||||
}
|
||||
assert(head > buffer->string && head < ARRAY_END(buffer->string));
|
||||
*--head = '0' + (char)i;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
__cold char *ratio2percent(uint64_t value, uint64_t whole, ratio2digits_buffer_t *buffer) {
|
||||
while (unlikely(value > UINT64_MAX / 100)) {
|
||||
value >>= 1;
|
||||
whole >>= 1;
|
||||
}
|
||||
const bool rough = whole >= value && (!value || value > whole / 16);
|
||||
return ratio2digits(value * 100, whole, buffer, rough ? 1 : 2);
|
||||
}
|
||||
|
||||
@@ -76,3 +76,10 @@ MDBX_MAYBE_UNUSED static inline uint64_t monotime_since_cached(uint64_t begin_ti
|
||||
}
|
||||
return cache->value - begin_timestamp;
|
||||
}
|
||||
|
||||
typedef struct ratio2digits_buffer {
|
||||
char string[1 + 20 + 1 + 19 + 1];
|
||||
} ratio2digits_buffer_t;
|
||||
|
||||
char *ratio2digits(const uint64_t v, const uint64_t d, ratio2digits_buffer_t *const buffer, int precision);
|
||||
char *ratio2percent(const uint64_t v, const uint64_t d, ratio2digits_buffer_t *const buffer);
|
||||
|
||||
Reference in New Issue
Block a user