diff --git a/src/api-env.c b/src/api-env.c index 9115370e..1e8988b6 100644 --- a/src/api-env.c +++ b/src/api-env.c @@ -3,35 +3,35 @@ #include "internals.h" -__cold static intptr_t reasonable_db_maxsize(intptr_t *cached_result) { - if (*cached_result == 0) { +__cold static intptr_t reasonable_db_maxsize(void) { + static intptr_t cached_result; + if (cached_result == 0) { intptr_t pagesize, total_ram_pages; if (unlikely(mdbx_get_sysraminfo(&pagesize, &total_ram_pages, nullptr) != MDBX_SUCCESS)) - return *cached_result = MAX_MAPSIZE32 /* the 32-bit limit is good enough - for fallback */ - ; + /* the 32-bit limit is good enough for fallback */ + return cached_result = MAX_MAPSIZE32; if (unlikely((size_t)total_ram_pages * 2 > MAX_MAPSIZE / (size_t)pagesize)) - return *cached_result = MAX_MAPSIZE; + return cached_result = MAX_MAPSIZE; assert(MAX_MAPSIZE >= (size_t)(total_ram_pages * pagesize * 2)); /* Suggesting should not be more than golden ratio of the size of RAM. */ - *cached_result = (intptr_t)((size_t)total_ram_pages * 207 >> 7) * pagesize; + cached_result = (intptr_t)((size_t)total_ram_pages * 207 >> 7) * pagesize; /* Round to the nearest human-readable granulation. */ for (size_t unit = MEGABYTE; unit; unit <<= 5) { - const size_t floor = floor_powerof2(*cached_result, unit); - const size_t ceil = ceil_powerof2(*cached_result, unit); - const size_t threshold = (size_t)*cached_result >> 4; + const size_t floor = floor_powerof2(cached_result, unit); + const size_t ceil = ceil_powerof2(cached_result, unit); + const size_t threshold = (size_t)cached_result >> 4; const bool down = - *cached_result - floor < ceil - *cached_result || ceil > MAX_MAPSIZE; - if (threshold < (down ? *cached_result - floor : ceil - *cached_result)) + cached_result - floor < ceil - cached_result || ceil > MAX_MAPSIZE; + if (threshold < (down ? cached_result - floor : ceil - cached_result)) break; - *cached_result = down ? floor : ceil; + cached_result = down ? floor : ceil; } } - return *cached_result; + return cached_result; } __cold static int check_alternative_lck_absent(const pathchar_t *lck_pathname) { @@ -1023,7 +1023,6 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, } #endif /* MDBX_DEBUG */ - intptr_t reasonable_maxsize_cache = 0; if (env->dxb_mmap.base) { /* env already mapped */ if (unlikely(env->flags & MDBX_RDONLY)) @@ -1089,16 +1088,17 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, pagesize = MDBX_MIN_PAGESIZE; /* choose pagesize */ - intptr_t max_size = (size_now > size_lower) ? size_now : size_lower; - max_size = (size_upper > max_size) ? size_upper : max_size; - if (max_size < 0 /* default */) - max_size = DEFAULT_MAPSIZE; - else if (max_size == 0 /* minimal */) - max_size = MIN_MAPSIZE; - else if (max_size >= (intptr_t)MAX_MAPSIZE /* maximal */) - max_size = reasonable_db_maxsize(&reasonable_maxsize_cache); + intptr_t top = (size_now > size_lower) ? size_now : size_lower; + if (size_upper > top) + top = size_upper; + if (top < 0 /* default */) + top = reasonable_db_maxsize(); + else if (top == 0 /* minimal */) + top = MIN_MAPSIZE; + else if (top >= (intptr_t)MAX_MAPSIZE /* maximal */) + top = MAX_MAPSIZE; - while (max_size > pagesize * (int64_t)(MAX_PAGENO + 1) && + while (top > pagesize * (int64_t)(MAX_PAGENO + 1) && pagesize < MDBX_MAX_PAGESIZE) pagesize <<= 1; } @@ -1116,7 +1116,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, size_lower = MIN_PAGENO * pagesize; } if (size_lower >= INTPTR_MAX) { - size_lower = reasonable_db_maxsize(&reasonable_maxsize_cache); + size_lower = reasonable_db_maxsize(); if ((size_t)size_lower / pagesize > MAX_PAGENO + 1) size_lower = pagesize * (MAX_PAGENO + 1); } @@ -1127,27 +1127,31 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, size_now = size_upper; } if (size_now >= INTPTR_MAX) { - size_now = reasonable_db_maxsize(&reasonable_maxsize_cache); + size_now = reasonable_db_maxsize(); if ((size_t)size_now / pagesize > MAX_PAGENO + 1) size_now = pagesize * (MAX_PAGENO + 1); } if (size_upper <= 0) { - if (size_now >= reasonable_db_maxsize(&reasonable_maxsize_cache) / 2) - size_upper = reasonable_db_maxsize(&reasonable_maxsize_cache); - else if (MAX_MAPSIZE != MAX_MAPSIZE32 && - (size_t)size_now >= MAX_MAPSIZE32 / 2 && + if (growth_step == 0 || size_upper == 0) + size_upper = size_now; + else if (size_now >= reasonable_db_maxsize() / 2) + size_upper = reasonable_db_maxsize(); + else if ((size_t)size_now >= MAX_MAPSIZE32 / 2 && (size_t)size_now <= MAX_MAPSIZE32 / 4 * 3) size_upper = MAX_MAPSIZE32; else { - size_upper = size_now + size_now; - if ((size_t)size_upper < DEFAULT_MAPSIZE * 2) - size_upper = DEFAULT_MAPSIZE * 2; + size_upper = ceil_powerof2(((size_t)size_now < MAX_MAPSIZE / 4) + ? size_now + size_now + : size_now + size_now / 2, + MEGABYTE * MDBX_WORDBITS * MDBX_WORDBITS / 32); + if ((size_t)size_upper > MAX_MAPSIZE) + size_upper = MAX_MAPSIZE; } if ((size_t)size_upper / pagesize > (MAX_PAGENO + 1)) size_upper = pagesize * (MAX_PAGENO + 1); } else if (size_upper >= INTPTR_MAX) { - size_upper = reasonable_db_maxsize(&reasonable_maxsize_cache); + size_upper = reasonable_db_maxsize(); if ((size_t)size_upper / pagesize > MAX_PAGENO + 1) size_upper = pagesize * (MAX_PAGENO + 1); } diff --git a/src/dxb.c b/src/dxb.c index cacf5975..9da9c009 100644 --- a/src/dxb.c +++ b/src/dxb.c @@ -589,7 +589,7 @@ __cold int dxb_setup(MDBX_env *env, const int lck_rc, if (!env->geo_in_bytes.now) { /* set defaults if not configured */ - err = mdbx_env_set_geometry(env, 0, -1, DEFAULT_MAPSIZE, -1, -1, -1); + err = mdbx_env_set_geometry(env, 0, -1, -1, -1, -1, -1); if (unlikely(err != MDBX_SUCCESS)) return err; } diff --git a/src/internals.h b/src/internals.h index 45d83725..d3c36bc9 100644 --- a/src/internals.h +++ b/src/internals.h @@ -494,11 +494,6 @@ struct MDBX_env { /* pseudo-error code, not exposed outside libmdbx */ #define MDBX_NO_ROOT (MDBX_LAST_ADDED_ERRCODE + 33) -/* Default size of memory map. - * This is certainly too small for any actual applications. Apps should - * always set the size explicitly using mdbx_env_set_geometry(). */ -#define DEFAULT_MAPSIZE MEGABYTE - /* Number of slots in the reader table. * This value was chosen somewhat arbitrarily. The 61 is a prime number, * and such readers plus a couple mutexes fit into single 4KB page.