mdbx: packing the 16-bit representations of grow step and shrink threshold values.

Using float point (exponential quantized) representation for internal 16-bit values
of grow step and shrink threshold when huge ones
.
To minimize the impact on compatibility, only the odd values inside the upper half
of the range (i.e. 32769..65533) are used for the new representation.

Resolve https://github.com/erthink/libmdbx/issues/166

Change-Id: I273127c1842deef0d7d8885b55a805b1463556eb
This commit is contained in:
Leonid Yuriev 2021-03-09 11:54:20 +03:00
parent 57af1d2310
commit 8e51a10908
3 changed files with 172 additions and 94 deletions

View File

@ -23,6 +23,10 @@ New features:
The `MDBX_DISABLE_PAGECHECKS=1` provides a performance boost of about 10% in CRUD scenarios,
and conjointly with the `MDBX_ENV_CHECKPID=0` and `MDBX_TXN_CHECKOWNER=0` options can yield
up to 30% more performance compared to LMDB.
- Using float point (exponential quantized) representation for internal 16-bit values
of grow step and shrink threshold when huge ones (https://github.com/erthink/libmdbx/issues/166).
To minimize the impact on compatibility, only the odd values inside the upper half
of the range (i.e. 32769..65533) are used for the new representation.
Fixes:

View File

@ -57,6 +57,59 @@ MDBX_NOTHROW_CONST_FUNCTION static unsigned log2n(size_t value) {
#endif
}
/* Pack/Unpack 16-bit values for Grow step & Shrink threshold */
MDBX_NOTHROW_CONST_FUNCTION static __inline pgno_t me2v(unsigned m,
unsigned e) {
assert(m < 2048 && e < 8);
return (pgno_t)(32768 + ((m + 1) << (e + 5)));
}
MDBX_NOTHROW_CONST_FUNCTION static __inline uint16_t v2me(size_t v,
unsigned e) {
assert(v > (e ? me2v(2047, e - 1) : 32768));
assert(v <= me2v(2047, e));
size_t m = (v - 32768 + (1 << (e + 5)) - 1) >> (e + 5);
m -= m > 0;
assert(m < 2048 && e < 8);
// f e d c b a 9 8 7 6 5 4 3 2 1 0
// 1 e e e m m m m m m m m m m m 1
const uint16_t pv = (uint16_t)(0x8001 + (e << 12) + (m << 1));
assert(pv != 65535);
return pv;
}
/* Convert 16-bit packed (exponential quantized) value to number of pages */
MDBX_NOTHROW_CONST_FUNCTION static pgno_t pv2pages(uint16_t pv) {
if ((pv & 0x8001) != 0x8001)
return pv;
if (pv == 65535)
return 65536;
// f e d c b a 9 8 7 6 5 4 3 2 1 0
// 1 e e e m m m m m m m m m m m 1
return me2v((pv >> 1) & 2047, (pv >> 12) & 7);
}
/* Convert number of pages to 16-bit packed (exponential quantized) value */
MDBX_NOTHROW_CONST_FUNCTION static uint16_t pages2pv(size_t pages) {
if (pages < 32769 || (pages < 65536 && (pages & 1) == 0))
return (uint16_t)pages;
if (pages <= me2v(2047, 0))
return v2me(pages, 0);
if (pages <= me2v(2047, 1))
return v2me(pages, 1);
if (pages <= me2v(2047, 2))
return v2me(pages, 2);
if (pages <= me2v(2047, 3))
return v2me(pages, 3);
if (pages <= me2v(2047, 4))
return v2me(pages, 4);
if (pages <= me2v(2047, 5))
return v2me(pages, 5);
if (pages <= me2v(2047, 6))
return v2me(pages, 6);
return (pages < me2v(2046, 7)) ? v2me(pages, 7) : 65533;
}
/*------------------------------------------------------------------------------
* Unaligned access */
@ -1296,6 +1349,17 @@ __cold void mdbx_rthc_global_init(void) {
}
bootid = mdbx_osal_bootid();
#if 0 /* debug */
for (unsigned i = 0; i < 65536; ++i) {
size_t pages = pv2pages(i);
unsigned x = pages2pv(pages);
size_t xp = pv2pages(x);
if (!(x == i || (x % 2 == 0 && x < 65536)) || pages != xp)
printf("%u => %zu => %u => %zu\n", i, pages, x, xp);
assert(pages == xp);
}
fflush(stdout);
#endif
}
/* dtor called for thread, i.e. for all mdbx's environment objects */
@ -6072,10 +6136,11 @@ no_loose:
rc = MDBX_NOTFOUND;
if (flags & MDBX_ALLOC_NEW) {
rc = MDBX_MAP_FULL;
if (next <= txn->mt_geo.upper && txn->mt_geo.grow) {
if (next <= txn->mt_geo.upper && txn->mt_geo.grow_pv) {
mdbx_assert(env, next > txn->mt_end_pgno);
const pgno_t grow_step = pv2pages(txn->mt_geo.grow_pv);
pgno_t aligned = pgno_align2os_pgno(
env, pgno_add(next, txn->mt_geo.grow - next % txn->mt_geo.grow));
env, pgno_add(next, grow_step - next % grow_step));
if (aligned > txn->mt_geo.upper)
aligned = txn->mt_geo.upper;
@ -9681,7 +9746,7 @@ mdbx_validate_meta(MDBX_env *env, MDBX_meta *const meta, uint64_t *filesize,
page->mp_pgno, meta->mm_dbs[MAIN_DBI].md_root,
meta->mm_dbs[FREE_DBI].md_root, meta->mm_geo.lower,
meta->mm_geo.next, meta->mm_geo.now, meta->mm_geo.upper,
meta->mm_geo.grow, meta->mm_geo.shrink,
pv2pages(meta->mm_geo.grow_pv), pv2pages(meta->mm_geo.shrink_pv),
unaligned_peek_u64(4, meta->mm_txnid_a), mdbx_durable_str(meta));
/* LY: check min-pages value */
@ -9935,8 +10000,9 @@ static MDBX_page *__cold mdbx_meta_model(const MDBX_env *env, MDBX_page *model,
model_meta->mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower);
model_meta->mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper);
model_meta->mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow);
model_meta->mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink);
model_meta->mm_geo.grow_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.grow));
model_meta->mm_geo.shrink_pv =
pages2pv(bytes2pgno(env, env->me_dbgeo.shrink));
model_meta->mm_geo.now = bytes2pgno(env, env->me_dbgeo.now);
model_meta->mm_geo.next = NUM_METAS;
@ -9946,10 +10012,10 @@ static MDBX_page *__cold mdbx_meta_model(const MDBX_env *env, MDBX_page *model,
mdbx_ensure(env, model_meta->mm_geo.now <= model_meta->mm_geo.upper);
mdbx_ensure(env, model_meta->mm_geo.next >= MIN_PAGENO);
mdbx_ensure(env, model_meta->mm_geo.next <= model_meta->mm_geo.now);
mdbx_ensure(env,
model_meta->mm_geo.grow == bytes2pgno(env, env->me_dbgeo.grow));
mdbx_ensure(env, model_meta->mm_geo.shrink ==
bytes2pgno(env, env->me_dbgeo.shrink));
mdbx_ensure(env, model_meta->mm_geo.grow_pv ==
pages2pv(pv2pages(model_meta->mm_geo.grow_pv)));
mdbx_ensure(env, model_meta->mm_geo.shrink_pv ==
pages2pv(pv2pages(model_meta->mm_geo.shrink_pv)));
model_meta->mm_psize = env->me_psize;
model_meta->mm_flags = (uint16_t)env->me_flags;
@ -10074,13 +10140,17 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
/* LY: check conditions to shrink datafile */
const pgno_t backlog_gap = 3 + pending->mm_dbs[FREE_DBI].md_depth * 3;
if (pending->mm_geo.shrink && pending->mm_geo.now - pending->mm_geo.next >
pending->mm_geo.shrink + backlog_gap) {
pgno_t shrink_step = 0;
if (pending->mm_geo.shrink_pv &&
pending->mm_geo.now - pending->mm_geo.next >
(shrink_step = pv2pages(pending->mm_geo.shrink_pv)) + backlog_gap) {
if (pending->mm_geo.now > largest_pgno &&
pending->mm_geo.now - largest_pgno >
pending->mm_geo.shrink + backlog_gap) {
const pgno_t aligner = pending->mm_geo.grow ? pending->mm_geo.grow
: pending->mm_geo.shrink;
pending->mm_geo.now - largest_pgno > shrink_step + backlog_gap) {
pgno_t grow_step = 0;
const pgno_t aligner =
pending->mm_geo.grow_pv
? (grow_step = pv2pages(pending->mm_geo.grow_pv))
: shrink_step;
const pgno_t with_backlog_gap = largest_pgno + backlog_gap;
const pgno_t aligned = pgno_align2os_pgno(
env, with_backlog_gap + aligner - with_backlog_gap % aligner);
@ -10168,15 +10238,15 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
}
/* LY: step#2 - update meta-page. */
mdbx_debug("writing meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO
", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
" +%u -%u, txn_id %" PRIaTXN ", %s",
data_page(target)->mp_pgno, pending->mm_dbs[MAIN_DBI].md_root,
pending->mm_dbs[FREE_DBI].md_root, pending->mm_geo.lower,
pending->mm_geo.next, pending->mm_geo.now, pending->mm_geo.upper,
pending->mm_geo.grow, pending->mm_geo.shrink,
unaligned_peek_u64(4, pending->mm_txnid_a),
mdbx_durable_str(pending));
mdbx_debug(
"writing meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO
", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
" +%u -%u, txn_id %" PRIaTXN ", %s",
data_page(target)->mp_pgno, pending->mm_dbs[MAIN_DBI].md_root,
pending->mm_dbs[FREE_DBI].md_root, pending->mm_geo.lower,
pending->mm_geo.next, pending->mm_geo.now, pending->mm_geo.upper,
pv2pages(pending->mm_geo.grow_pv), pv2pages(pending->mm_geo.shrink_pv),
unaligned_peek_u64(4, pending->mm_txnid_a), mdbx_durable_str(pending));
mdbx_debug("meta0: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO
"/%" PRIaPGNO,
@ -10458,9 +10528,9 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
if (size_upper < 0)
size_upper = pgno2bytes(env, head->mm_geo.upper);
if (growth_step < 0)
growth_step = pgno2bytes(env, head->mm_geo.grow);
growth_step = pgno2bytes(env, pv2pages(head->mm_geo.grow_pv));
if (shrink_threshold < 0)
shrink_threshold = pgno2bytes(env, head->mm_geo.shrink);
shrink_threshold = pgno2bytes(env, pv2pages(head->mm_geo.shrink_pv));
if (pagesize != (intptr_t)env->me_psize) {
rc = MDBX_EINVAL;
@ -10603,21 +10673,18 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
if (growth_step == 0 && shrink_threshold > 0)
growth_step = 1;
growth_step = ceil_powerof2(growth_step, unit);
if (bytes2pgno(env, growth_step) > UINT16_MAX)
growth_step = pgno2bytes(env, UINT16_MAX);
if (shrink_threshold < 0)
shrink_threshold = growth_step + growth_step;
shrink_threshold = ceil_powerof2(shrink_threshold, unit);
if (bytes2pgno(env, shrink_threshold) > UINT16_MAX)
shrink_threshold = pgno2bytes(env, UINT16_MAX);
/* save user's geo-params for future open/create */
env->me_dbgeo.lower = size_lower;
env->me_dbgeo.now = size_now;
env->me_dbgeo.upper = size_upper;
env->me_dbgeo.grow = growth_step;
env->me_dbgeo.shrink = shrink_threshold;
env->me_dbgeo.grow = pv2pages(pages2pv(growth_step / pagesize)) * pagesize;
env->me_dbgeo.shrink =
pv2pages(pages2pv(shrink_threshold / pagesize)) * pagesize;
rc = MDBX_SUCCESS;
mdbx_ensure(env, pagesize >= MIN_PAGESIZE);
@ -10650,7 +10717,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
mdbx_ensure(env, pagesize == (intptr_t)env->me_psize);
MDBX_meta meta;
MDBX_meta *head = nullptr;
const mdbx_geo_t *current_geo;
const MDBX_geo *current_geo;
if (inside_txn) {
current_geo = &env->me_txn->mt_geo;
} else {
@ -10659,12 +10726,12 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
current_geo = &meta.mm_geo;
}
mdbx_geo_t new_geo;
MDBX_geo new_geo;
new_geo.lower = bytes2pgno(env, env->me_dbgeo.lower);
new_geo.now = bytes2pgno(env, env->me_dbgeo.now);
new_geo.upper = bytes2pgno(env, env->me_dbgeo.upper);
new_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow);
new_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink);
new_geo.grow_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.grow));
new_geo.shrink_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.shrink));
new_geo.next = current_geo->next;
mdbx_ensure(env,
@ -10673,10 +10740,9 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
pgno_align2os_bytes(env, new_geo.upper) == env->me_dbgeo.upper);
mdbx_ensure(env,
pgno_align2os_bytes(env, new_geo.now) == env->me_dbgeo.now);
mdbx_ensure(env, new_geo.grow_pv == pages2pv(pv2pages(new_geo.grow_pv)));
mdbx_ensure(env,
pgno_align2os_bytes(env, new_geo.grow) == env->me_dbgeo.grow);
mdbx_ensure(env, pgno_align2os_bytes(env, new_geo.shrink) ==
env->me_dbgeo.shrink);
new_geo.shrink_pv == pages2pv(pv2pages(new_geo.shrink_pv)));
mdbx_ensure(env, env->me_dbgeo.lower >= MIN_MAPSIZE);
mdbx_ensure(env, new_geo.lower >= MIN_PAGENO);
@ -10686,11 +10752,12 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
mdbx_ensure(env, new_geo.upper >= new_geo.now);
mdbx_ensure(env, new_geo.now >= new_geo.lower);
if (memcmp(current_geo, &new_geo, sizeof(mdbx_geo_t)) != 0) {
if (memcmp(current_geo, &new_geo, sizeof(MDBX_geo)) != 0) {
#if defined(_WIN32) || defined(_WIN64)
/* Was DB shrinking disabled before and now it will be enabled? */
if (new_geo.lower < new_geo.upper && new_geo.shrink &&
!(current_geo->lower < current_geo->upper && current_geo->shrink)) {
if (new_geo.lower < new_geo.upper && new_geo.shrink_pv &&
!(current_geo->lower < current_geo->upper &&
current_geo->shrink_pv)) {
if (!env->me_lck) {
rc = MDBX_EPERM;
goto bailout;
@ -10823,13 +10890,13 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
#endif
}
mdbx_verbose("header: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO
"/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
" +%u -%u, txn_id %" PRIaTXN ", %s",
meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root,
meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now,
meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink,
unaligned_peek_u64(4, meta.mm_txnid_a), mdbx_durable_str(&meta));
mdbx_verbose(
"header: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO "/%" PRIaPGNO
"-%" PRIaPGNO "/%" PRIaPGNO " +%u -%u, txn_id %" PRIaTXN ", %s",
meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root,
meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, meta.mm_geo.upper,
pv2pages(meta.mm_geo.grow_pv), pv2pages(meta.mm_geo.shrink_pv),
unaligned_peek_u64(4, meta.mm_txnid_a), mdbx_durable_str(&meta));
mdbx_setup_pagesize(env, meta.mm_psize);
const size_t used_bytes = pgno2bytes(env, meta.mm_geo.next);
@ -10842,8 +10909,8 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
const size_t pagesize = meta.mm_psize;
err = mdbx_env_set_geometry(
env, meta.mm_geo.lower * pagesize, meta.mm_geo.now * pagesize,
meta.mm_geo.upper * pagesize, meta.mm_geo.grow * pagesize,
meta.mm_geo.shrink * pagesize, meta.mm_psize);
meta.mm_geo.upper * pagesize, pv2pages(meta.mm_geo.grow_pv) * pagesize,
pv2pages(meta.mm_geo.shrink_pv) * pagesize, meta.mm_psize);
if (unlikely(err != MDBX_SUCCESS)) {
mdbx_error("%s: err %d", "could not apply preconfigured geometry from db",
err);
@ -10865,9 +10932,9 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
bytes_align2os_bytes(env, env->me_dbgeo.lower) !=
pgno2bytes(env, meta.mm_geo.lower) ||
bytes_align2os_bytes(env, env->me_dbgeo.shrink) !=
pgno2bytes(env, meta.mm_geo.shrink) ||
pgno2bytes(env, pv2pages(meta.mm_geo.shrink_pv)) ||
bytes_align2os_bytes(env, env->me_dbgeo.grow) !=
pgno2bytes(env, meta.mm_geo.grow)) {
pgno2bytes(env, pv2pages(meta.mm_geo.grow_pv))) {
if (env->me_dbgeo.shrink && env->me_dbgeo.now > used_bytes)
/* pre-shrink if enabled */
@ -10887,15 +10954,16 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now);
meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower);
meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper);
meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow);
meta.mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink);
meta.mm_geo.grow_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.grow));
meta.mm_geo.shrink_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.shrink));
mdbx_verbose("amended: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO
"/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO
" +%u -%u, txn_id %" PRIaTXN ", %s",
meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root,
meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now,
meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink,
meta.mm_geo.upper, pv2pages(meta.mm_geo.grow_pv),
pv2pages(meta.mm_geo.shrink_pv),
unaligned_peek_u64(4, meta.mm_txnid_a),
mdbx_durable_str(&meta));
} else {
@ -10910,8 +10978,8 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
env->me_dbgeo.now = pgno2bytes(env, meta.mm_geo.now);
env->me_dbgeo.lower = pgno2bytes(env, meta.mm_geo.lower);
env->me_dbgeo.upper = pgno2bytes(env, meta.mm_geo.upper);
env->me_dbgeo.grow = pgno2bytes(env, meta.mm_geo.grow);
env->me_dbgeo.shrink = pgno2bytes(env, meta.mm_geo.shrink);
env->me_dbgeo.grow = pgno2bytes(env, pv2pages(meta.mm_geo.grow_pv));
env->me_dbgeo.shrink = pgno2bytes(env, pv2pages(meta.mm_geo.shrink_pv));
}
mdbx_ensure(env,
@ -11133,14 +11201,15 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) {
if ((env->me_flags & MDBX_RDONLY) != 0 ||
/* recovery mode */ env->me_stuck_meta >= 0) {
mdbx_warning("skipped update meta.geo in %s mode: from l%" PRIaPGNO
"-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u, to l%" PRIaPGNO
"-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u",
(env->me_stuck_meta < 0) ? "read-only" : "recovery",
head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper,
head->mm_geo.shrink, head->mm_geo.grow, meta.mm_geo.lower,
meta.mm_geo.now, meta.mm_geo.upper, meta.mm_geo.shrink,
meta.mm_geo.grow);
mdbx_warning(
"skipped update meta.geo in %s mode: from l%" PRIaPGNO
"-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u, to l%" PRIaPGNO
"-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u",
(env->me_stuck_meta < 0) ? "read-only" : "recovery",
head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper,
pv2pages(head->mm_geo.shrink_pv), pv2pages(head->mm_geo.grow_pv),
meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper,
pv2pages(meta.mm_geo.shrink_pv), pv2pages(meta.mm_geo.grow_pv));
} else {
const txnid_t txnid = mdbx_meta_txnid_stable(env, head);
const txnid_t next_txnid = safe64_txnid_next(txnid);
@ -11154,9 +11223,11 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
"to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO
"/s%u-g%u (txn#%" PRIaTXN ")",
head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper,
head->mm_geo.shrink, head->mm_geo.grow, txnid,
meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper,
meta.mm_geo.shrink, meta.mm_geo.grow, next_txnid);
pv2pages(head->mm_geo.shrink_pv),
pv2pages(head->mm_geo.grow_pv), txnid, meta.mm_geo.lower,
meta.mm_geo.now, meta.mm_geo.upper,
pv2pages(meta.mm_geo.shrink_pv),
pv2pages(meta.mm_geo.grow_pv), next_txnid);
mdbx_ensure(env, mdbx_meta_eq(env, &meta, head));
mdbx_meta_set_txnid(env, &meta, next_txnid);
@ -11168,10 +11239,11 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) {
"to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO
"/s%u-g%u (txn#%" PRIaTXN ")",
err, head->mm_geo.lower, head->mm_geo.now,
head->mm_geo.upper, head->mm_geo.shrink, head->mm_geo.grow,
txnid, meta.mm_geo.lower, meta.mm_geo.now,
meta.mm_geo.upper, meta.mm_geo.shrink, meta.mm_geo.grow,
next_txnid);
head->mm_geo.upper, pv2pages(head->mm_geo.shrink_pv),
pv2pages(head->mm_geo.grow_pv), txnid, meta.mm_geo.lower,
meta.mm_geo.now, meta.mm_geo.upper,
pv2pages(meta.mm_geo.shrink_pv),
pv2pages(meta.mm_geo.grow_pv), next_txnid);
return err;
}
}
@ -17729,8 +17801,8 @@ static __cold void compact_fixup_meta(MDBX_env *env, MDBX_meta *meta) {
/* Calculate filesize taking in account shrink/growing thresholds */
if (meta->mm_geo.next != meta->mm_geo.now) {
meta->mm_geo.now = meta->mm_geo.next;
const pgno_t aligner =
meta->mm_geo.grow ? meta->mm_geo.grow : meta->mm_geo.shrink;
const pgno_t aligner = pv2pages(
meta->mm_geo.grow_pv ? meta->mm_geo.grow_pv : meta->mm_geo.shrink_pv);
if (aligner) {
const pgno_t aligned = pgno_align2os_pgno(
env, meta->mm_geo.next + aligner - meta->mm_geo.next % aligner);
@ -17751,13 +17823,13 @@ static __cold void compact_fixup_meta(MDBX_env *env, MDBX_meta *meta) {
/* Make resizeable */
static __cold void make_sizeable(MDBX_meta *meta) {
meta->mm_geo.lower = MIN_PAGENO;
if (meta->mm_geo.grow == 0) {
const size_t step = 1 + (meta->mm_geo.upper - meta->mm_geo.lower) / 42;
meta->mm_geo.grow = (step < UINT16_MAX) ? (uint16_t)step : UINT16_MAX;
if (meta->mm_geo.grow_pv == 0) {
const pgno_t step = 1 + (meta->mm_geo.upper - meta->mm_geo.lower) / 42;
meta->mm_geo.grow_pv = pages2pv(step);
}
if (meta->mm_geo.shrink == 0) {
const size_t step = meta->mm_geo.grow + meta->mm_geo.grow;
meta->mm_geo.shrink = (step < UINT16_MAX) ? (uint16_t)step : UINT16_MAX;
if (meta->mm_geo.shrink_pv == 0) {
const pgno_t step = pv2pages(meta->mm_geo.grow_pv) << 1;
meta->mm_geo.shrink_pv = pages2pv(step);
}
}
@ -18410,8 +18482,8 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn,
}
arg->mi_geo.lower = pgno2bytes(env, txn_meta->mm_geo.lower);
arg->mi_geo.upper = pgno2bytes(env, txn_meta->mm_geo.upper);
arg->mi_geo.shrink = pgno2bytes(env, txn_meta->mm_geo.shrink);
arg->mi_geo.grow = pgno2bytes(env, txn_meta->mm_geo.grow);
arg->mi_geo.shrink = pgno2bytes(env, pv2pages(txn_meta->mm_geo.shrink_pv));
arg->mi_geo.grow = pgno2bytes(env, pv2pages(txn_meta->mm_geo.grow_pv));
unsynced_pages = atomic_load32(env->me_unsynced_pages, mo_Relaxed) +
(atomic_load32(env->me_meta_sync_txnid, mo_Relaxed) !=
(uint32_t)arg->mi_last_pgno);

View File

@ -300,15 +300,17 @@ typedef struct MDBX_db {
} MDBX_db;
/* database size-related parameters */
typedef struct mdbx_geo_t {
uint16_t grow; /* datafile growth step in pages */
uint16_t shrink; /* datafile shrink threshold in pages */
pgno_t lower; /* minimal size of datafile in pages */
pgno_t upper; /* maximal size of datafile in pages */
pgno_t now; /* current size of datafile in pages */
pgno_t next; /* first unused page in the datafile,
* but actually the file may be shorter. */
} mdbx_geo_t;
typedef struct MDBX_geo {
uint16_t grow_pv; /* datafile growth step as a 16-bit packed (exponential
quantized) value */
uint16_t shrink_pv; /* datafile shrink threshold as a 16-bit packed
(exponential quantized) value */
pgno_t lower; /* minimal size of datafile in pages */
pgno_t upper; /* maximal size of datafile in pages */
pgno_t now; /* current size of datafile in pages */
pgno_t next; /* first unused page in the datafile,
but actually the file may be shorter. */
} MDBX_geo;
/* Meta page content.
* A meta page is the start point for accessing a database snapshot.
@ -327,7 +329,7 @@ typedef struct MDBX_meta {
uint8_t mm_extra_pagehdr; /* extra bytes in the page header,
* zero (nothing) for now */
mdbx_geo_t mm_geo; /* database size-related parameters */
MDBX_geo mm_geo; /* database size-related parameters */
MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */
/* The size of pages used in this DB */
@ -731,7 +733,7 @@ struct MDBX_txn {
MDBX_txn *mt_parent; /* parent of a nested txn */
/* Nested txn under this txn, set together with flag MDBX_TXN_HAS_CHILD */
MDBX_txn *mt_child;
mdbx_geo_t mt_geo;
MDBX_geo mt_geo;
/* next unallocated page */
#define mt_next_pgno mt_geo.next
/* corresponding to the current size of datafile */