From 9ad4fe8f96eca31eff99edea91630a0c7c5f3e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Wed, 3 Sep 2025 21:49:17 +0300 Subject: [PATCH] mdbx: refine ceil/rounding to be perfectly close to system allocation granularity. --- src/api-env.c | 32 +++++++++++++++++--------------- src/dxb.c | 20 ++++++++++---------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/api-env.c b/src/api-env.c index e68fc589..6c50589d 100644 --- a/src/api-env.c +++ b/src/api-env.c @@ -970,23 +970,24 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si /* get untouched params from current TXN or DB */ if (pagesize <= 0 || pagesize >= INT_MAX) pagesize = env->ps; + if (pagesize != (intptr_t)env->ps) { + rc = MDBX_EINVAL; + goto bailout; + } + const geo_t *const geo = env->txn ? &env->txn->geo : &meta_recent(env, &env->basal_txn->wr.troika).ptr_c->geometry; if (size_lower < 0) size_lower = pgno2bytes(env, geo->lower); if (size_now < 0) - size_now = pgno2bytes(env, geo->now); + size_now = pgno_ceil2sp_bytes(env, geo->now); if (size_upper < 0) - size_upper = pgno2bytes(env, geo->upper); + size_upper = pgno_ceil2sp_bytes(env, geo->upper); if (growth_step < 0) growth_step = pgno2bytes(env, pv2pages(geo->grow_pv)); if (shrink_threshold < 0) shrink_threshold = pgno2bytes(env, pv2pages(geo->shrink_pv)); - if (pagesize != (intptr_t)env->ps) { - rc = MDBX_EINVAL; - goto bailout; - } - const size_t usedbytes = pgno2bytes(env, mvcc_snapshot_largest(env, geo->first_unallocated)); + const size_t usedbytes = pgno_ceil2sp_bytes(env, mvcc_snapshot_largest(env, geo->first_unallocated)); if ((size_t)size_upper < usedbytes) { rc = MDBX_MAP_FULL; goto bailout; @@ -1098,21 +1099,22 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si goto bailout; } - const size_t unit = (globals.sys_pagesize > (size_t)pagesize) ? globals.sys_pagesize : (size_t)pagesize; - size_lower = ceil_powerof2(size_lower, unit); - size_upper = ceil_powerof2(size_upper, unit); - size_now = ceil_powerof2(size_now, unit); + const size_t unit_ps = (globals.sys_pagesize > (size_t)pagesize) ? globals.sys_pagesize : (size_t)pagesize; + const size_t unit_ag = (globals.sys_allocation_granularity > unit_ps) ? globals.sys_allocation_granularity : unit_ps; + size_lower = ceil_powerof2(size_lower, unit_ps); + size_upper = ceil_powerof2(size_upper, unit_ag); + size_now = ceil_powerof2(size_now, unit_ag); /* LY: подбираем значение size_upper: * - кратное размеру страницы * - без нарушения MAX_MAPSIZE и MAX_PAGENO */ while (unlikely((size_t)size_upper > MAX_MAPSIZE || (uint64_t)size_upper / pagesize > MAX_PAGENO + 1)) { - if ((size_t)size_upper < unit + MIN_MAPSIZE || (size_t)size_upper < (size_t)pagesize * (MIN_PAGENO + 1)) { + if ((size_t)size_upper < unit_ag + MIN_MAPSIZE || (size_t)size_upper < (size_t)pagesize * (MIN_PAGENO + 1)) { /* паранойа на случай переполнения при невероятных значениях */ rc = MDBX_EINVAL; goto bailout; } - size_upper -= unit; + size_upper -= unit_ag; if ((size_t)size_upper < (size_t)size_lower) size_lower = size_upper; } @@ -1139,11 +1141,11 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si } if (growth_step == 0 && shrink_threshold > 0) growth_step = 1; - growth_step = ceil_powerof2(growth_step, unit); + growth_step = ceil_powerof2(growth_step, unit_ag); if (shrink_threshold < 0) shrink_threshold = growth_step + growth_step; - shrink_threshold = ceil_powerof2(shrink_threshold, unit); + shrink_threshold = ceil_powerof2(shrink_threshold, unit_ag); //---------------------------------------------------------------------------- diff --git a/src/dxb.c b/src/dxb.c index e76661a6..85a9bf75 100644 --- a/src/dxb.c +++ b/src/dxb.c @@ -614,11 +614,11 @@ __cold int dxb_setup(MDBX_env *env, const int lck_rc, const mdbx_mode_t mode_bit /* altering fields to match geometry given from user */ expected_filesize = pgno_ceil2sp_bytes(env, header.geometry.now); - header.geometry.now = bytes2pgno(env, env->geo_in_bytes.now); - header.geometry.lower = bytes2pgno(env, env->geo_in_bytes.lower); - header.geometry.upper = bytes2pgno(env, env->geo_in_bytes.upper); - header.geometry.grow_pv = pages2pv(bytes2pgno(env, env->geo_in_bytes.grow)); - header.geometry.shrink_pv = pages2pv(bytes2pgno(env, env->geo_in_bytes.shrink)); + header.geometry.now = bytes_ceil2sp_pgno(env, env->geo_in_bytes.now); + header.geometry.lower = bytes_ceil2sp_pgno(env, env->geo_in_bytes.lower); + header.geometry.upper = bytes_ceil2sp_pgno(env, env->geo_in_bytes.upper); + header.geometry.grow_pv = pages2pv(bytes_ceil2sp_pgno(env, env->geo_in_bytes.grow)); + header.geometry.shrink_pv = pages2pv(bytes_ceil2sp_pgno(env, env->geo_in_bytes.shrink)); VERBOSE("amending: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO " +%u -%u, txn_id %" PRIaTXN ", %s", @@ -632,11 +632,11 @@ __cold int dxb_setup(MDBX_env *env, const int lck_rc, const mdbx_mode_t mode_bit ENSURE(env, header.geometry.now >= header.geometry.first_unallocated); } else { /* geo-params are not pre-configured by user, get current values from the meta. */ - env->geo_in_bytes.now = pgno2bytes(env, header.geometry.now); - env->geo_in_bytes.lower = pgno2bytes(env, header.geometry.lower); - env->geo_in_bytes.upper = pgno2bytes(env, header.geometry.upper); - env->geo_in_bytes.grow = pgno2bytes(env, pv2pages(header.geometry.grow_pv)); - env->geo_in_bytes.shrink = pgno2bytes(env, pv2pages(header.geometry.shrink_pv)); + env->geo_in_bytes.now = pgno_ceil2sp_bytes(env, header.geometry.now); + env->geo_in_bytes.lower = pgno_ceil2sp_bytes(env, header.geometry.lower); + env->geo_in_bytes.upper = pgno_ceil2sp_bytes(env, header.geometry.upper); + env->geo_in_bytes.grow = pgno_ceil2sp_bytes(env, pv2pages(header.geometry.grow_pv)); + env->geo_in_bytes.shrink = pgno_ceil2sp_bytes(env, pv2pages(header.geometry.shrink_pv)); } ENSURE(env, pgno_ceil2sp_bytes(env, header.geometry.now) == env->geo_in_bytes.now);