mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-30 11:29:19 +08:00
mdbx: guess a reasonable maximum DB size for the default upper limit of geometry.
Fixes https://github.com/erthink/libmdbx/issues/183 Change-Id: Ic7b616e229d3008fda49e5a04121e22997ac53ea
This commit is contained in:
parent
8ff44026c3
commit
c14e4235ee
48
src/core.c
48
src/core.c
@ -10517,6 +10517,41 @@ bailout:
|
||||
return rc;
|
||||
}
|
||||
|
||||
__cold static intptr_t get_reasonable_db_maxsize(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 MAX_MAPSIZE32 /* the 32-bit limit is good enough for fallback */;
|
||||
|
||||
if (unlikely((size_t)total_ram_pages * 2 > MAX_MAPSIZE / (size_t)pagesize))
|
||||
return 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)(total_ram_pages * pagesize * 1.6180339887498948482);
|
||||
|
||||
/* Round to the nearest human-readable granulation. */
|
||||
for (int i = 10; i < MDBX_WORDBITS - 1; i += 10) {
|
||||
const size_t unit = (size_t)1 << i;
|
||||
const size_t floor = floor_powerof2(*cached_result, unit);
|
||||
const size_t ceil = ceil_powerof2(*cached_result, unit);
|
||||
if (*cached_result - floor < ceil - *cached_result ||
|
||||
ceil > MAX_MAPSIZE) {
|
||||
if (*cached_result - floor > (size_t)*cached_result / 16)
|
||||
break;
|
||||
*cached_result = floor;
|
||||
} else {
|
||||
if (ceil - *cached_result > (size_t)*cached_result / 16)
|
||||
break;
|
||||
*cached_result = ceil;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *cached_result;
|
||||
}
|
||||
|
||||
__cold LIBMDBX_API int
|
||||
mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
intptr_t size_upper, intptr_t growth_step,
|
||||
@ -10535,6 +10570,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
shrink_threshold = 1;
|
||||
#endif
|
||||
|
||||
intptr_t reasonable_maxsize = 0;
|
||||
bool need_unlock = false;
|
||||
if (env->me_map) {
|
||||
/* env already mapped */
|
||||
@ -10604,7 +10640,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
else if (max_size == 0 /* minimal */)
|
||||
max_size = MIN_MAPSIZE;
|
||||
else if (max_size >= (intptr_t)MAX_MAPSIZE /* maximal */)
|
||||
max_size = MAX_MAPSIZE;
|
||||
max_size = get_reasonable_db_maxsize(&reasonable_maxsize);
|
||||
|
||||
while (max_size > pagesize * (int64_t)MAX_PAGENO &&
|
||||
pagesize < MAX_PAGESIZE)
|
||||
@ -10624,7 +10660,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
size_lower = MIN_PAGENO * pagesize;
|
||||
}
|
||||
if (size_lower >= INTPTR_MAX) {
|
||||
size_lower = MAX_MAPSIZE;
|
||||
size_lower = get_reasonable_db_maxsize(&reasonable_maxsize);
|
||||
if ((size_t)size_lower / pagesize > MAX_PAGENO)
|
||||
size_lower = pagesize * MAX_PAGENO;
|
||||
}
|
||||
@ -10635,14 +10671,14 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
size_now = size_upper;
|
||||
}
|
||||
if (size_now >= INTPTR_MAX) {
|
||||
size_now = MAX_MAPSIZE;
|
||||
size_now = get_reasonable_db_maxsize(&reasonable_maxsize);
|
||||
if ((size_t)size_now / pagesize > MAX_PAGENO)
|
||||
size_now = pagesize * MAX_PAGENO;
|
||||
}
|
||||
|
||||
if (size_upper <= 0) {
|
||||
if ((size_t)size_now >= MAX_MAPSIZE / 2)
|
||||
size_upper = MAX_MAPSIZE;
|
||||
if (size_now >= get_reasonable_db_maxsize(&reasonable_maxsize) / 2)
|
||||
size_upper = get_reasonable_db_maxsize(&reasonable_maxsize);
|
||||
else if (MAX_MAPSIZE != MAX_MAPSIZE32 &&
|
||||
(size_t)size_now >= MAX_MAPSIZE32 / 2 &&
|
||||
(size_t)size_now <= MAX_MAPSIZE32 / 4 * 3)
|
||||
@ -10655,7 +10691,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now,
|
||||
if ((size_t)size_upper / pagesize > MAX_PAGENO)
|
||||
size_upper = pagesize * MAX_PAGENO;
|
||||
} else if (size_upper >= INTPTR_MAX) {
|
||||
size_upper = MAX_MAPSIZE;
|
||||
size_upper = get_reasonable_db_maxsize(&reasonable_maxsize);
|
||||
if ((size_t)size_upper / pagesize > MAX_PAGENO)
|
||||
size_upper = pagesize * MAX_PAGENO;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user