mdbx: introduce MDBX_PGL_LIMIT.

Change-Id: Ifab1156ec22fb0908284298393f52c09c0731829
This commit is contained in:
Leonid Yuriev 2020-12-01 20:20:29 +03:00
parent 4cd08f0ef9
commit 0b62453f6d
4 changed files with 27 additions and 28 deletions

View File

@ -1183,6 +1183,7 @@ perror
PFILE
pflags
pgcount
PGL
pglist
pgno
pgnumber

View File

@ -398,10 +398,11 @@ __cold intptr_t mdbx_limits_valsize_max(intptr_t pagesize,
const unsigned page_ln2 = log2n(pagesize);
const size_t hard = 0x7FF00000ul;
const size_t hard_pages = hard >> page_ln2;
const size_t limit = (hard_pages < MDBX_DPL_TXNFULL / 3)
? hard
: ((size_t)MDBX_DPL_TXNFULL / 3 << page_ln2);
return (limit < MAX_MAPSIZE) ? limit / 2 : MAX_MAPSIZE / 2;
STATIC_ASSERT(MDBX_PGL_LIMIT <= MAX_PAGENO);
const size_t pages_limit = MDBX_PGL_LIMIT / 4;
const size_t limit =
(hard_pages < pages_limit) ? hard : (pages_limit << page_ln2);
return (limit < MAX_MAPSIZE / 2) ? limit : MAX_MAPSIZE / 2;
}
/* Calculate the size of a leaf node.
@ -2613,7 +2614,7 @@ static int lcklist_detach_locked(MDBX_env *env) {
/*----------------------------------------------------------------------------*/
static __always_inline size_t pnl2bytes(const size_t size) {
assert(size > 0 && size <= MDBX_PNL_MAX * 2);
assert(size > 0 && size <= MDBX_PGL_LIMIT);
size_t bytes =
ceil_powerof2(MDBX_ASSUME_MALLOC_OVERHEAD + sizeof(pgno_t) * (size + 2),
MDBX_PNL_GRANULATE * sizeof(pgno_t)) -
@ -2623,7 +2624,7 @@ static __always_inline size_t pnl2bytes(const size_t size) {
static __always_inline pgno_t bytes2pnl(const size_t bytes) {
size_t size = bytes / sizeof(pgno_t);
assert(size > 2 && size <= MDBX_PNL_MAX * 2);
assert(size > 2 && size <= MDBX_PGL_LIMIT);
return (pgno_t)size - 2;
}
@ -2650,7 +2651,7 @@ static void mdbx_pnl_free(MDBX_PNL pl) {
/* Shrink the PNL to the default size if it has grown larger */
static void mdbx_pnl_shrink(MDBX_PNL *ppl) {
assert(bytes2pnl(pnl2bytes(MDBX_PNL_INITIAL)) == MDBX_PNL_INITIAL);
assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX &&
assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PGL_LIMIT &&
MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl));
MDBX_PNL_SIZE(*ppl) = 0;
if (unlikely(MDBX_PNL_ALLOCLEN(*ppl) >
@ -2670,17 +2671,17 @@ static void mdbx_pnl_shrink(MDBX_PNL *ppl) {
/* Grow the PNL to the size growed to at least given size */
static int mdbx_pnl_reserve(MDBX_PNL *ppl, const size_t wanna) {
const size_t allocated = MDBX_PNL_ALLOCLEN(*ppl);
assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX &&
assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PGL_LIMIT &&
MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl));
if (likely(allocated >= wanna))
return MDBX_SUCCESS;
if (unlikely(wanna > /* paranoia */ MDBX_PNL_MAX))
if (unlikely(wanna > /* paranoia */ MDBX_PGL_LIMIT))
return MDBX_TXN_FULL;
const size_t size = (wanna + wanna - allocated < MDBX_PNL_MAX)
const size_t size = (wanna + wanna - allocated < MDBX_PGL_LIMIT)
? wanna + wanna - allocated
: MDBX_PNL_MAX;
: MDBX_PGL_LIMIT;
size_t bytes = pnl2bytes(size);
MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes);
if (likely(pl)) {
@ -2698,9 +2699,9 @@ static int mdbx_pnl_reserve(MDBX_PNL *ppl, const size_t wanna) {
/* Make room for num additional elements in an PNL */
static __always_inline int __must_check_result mdbx_pnl_need(MDBX_PNL *ppl,
size_t num) {
assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX &&
assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PGL_LIMIT &&
MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl));
assert(num <= MDBX_PNL_MAX);
assert(num <= MDBX_PGL_LIMIT);
const size_t wanna = MDBX_PNL_SIZE(*ppl) + num;
return likely(MDBX_PNL_ALLOCLEN(*ppl) >= wanna)
? MDBX_SUCCESS
@ -2802,8 +2803,8 @@ static bool mdbx_pnl_check(const MDBX_PNL pl, const pgno_t limit) {
if (likely(MDBX_PNL_SIZE(pl))) {
assert(MDBX_PNL_LEAST(pl) >= MIN_PAGENO);
assert(MDBX_PNL_MOST(pl) < limit);
assert(MDBX_PNL_SIZE(pl) <= MDBX_PNL_MAX);
if (unlikely(MDBX_PNL_SIZE(pl) > MDBX_PNL_MAX * 3 / 2))
assert(MDBX_PNL_SIZE(pl) <= MDBX_PGL_LIMIT);
if (unlikely(MDBX_PNL_SIZE(pl) > MDBX_PGL_LIMIT))
return false;
if (unlikely(MDBX_PNL_LEAST(pl) < MIN_PAGENO))
return false;
@ -2945,7 +2946,7 @@ static __always_inline int __must_check_result mdbx_txl_need(MDBX_TXL *ptl,
size_t num) {
assert(MDBX_PNL_SIZE(*ptl) <= MDBX_TXL_MAX &&
MDBX_PNL_ALLOCLEN(*ptl) >= MDBX_PNL_SIZE(*ptl));
assert(num <= MDBX_PNL_MAX);
assert(num <= MDBX_PGL_LIMIT);
const size_t wanna = (size_t)MDBX_PNL_SIZE(*ptl) + num;
return likely(MDBX_PNL_ALLOCLEN(*ptl) >= wanna)
? MDBX_SUCCESS
@ -2979,7 +2980,7 @@ static int __must_check_result mdbx_txl_append(MDBX_TXL *ptl, txnid_t id) {
#define DP_SORT_CMP(first, last) ((first).pgno < (last).pgno)
SORT_IMPL(dp_sort, false, MDBX_DP, DP_SORT_CMP)
static __always_inline MDBX_DPL mdbx_dpl_sort(MDBX_DPL dl) {
assert(dl->length <= MDBX_DPL_TXNFULL);
assert(dl->length <= MDBX_PGL_LIMIT);
assert(dl->sorted <= dl->length);
if (dl->sorted != dl->length) {
dl->sorted = dl->length;
@ -3071,7 +3072,7 @@ static __hot MDBX_page *mdbx_dpl_remove(MDBX_DPL dl, pgno_t prno) {
static __always_inline int __must_check_result
mdbx_dpl_append(MDBX_DPL dl, pgno_t pgno, MDBX_page *page) {
assert(dl->length <= MDBX_DPL_TXNFULL);
assert(dl->length <= MDBX_PGL_LIMIT);
if (mdbx_audit_enabled()) {
for (unsigned i = dl->length; i > 0; --i) {
assert(dl[i].pgno != pgno);
@ -5277,12 +5278,11 @@ skip_cache:
goto fail;
}
const unsigned gc_len = MDBX_PNL_SIZE(gc_pnl);
/* TODO: provide a user-configurable threshold */
if (unlikely(gc_len + MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) >
env->me_options.rp_augment_limit) &&
(pgno_add(txn->mt_next_pgno, num) <= txn->mt_geo.upper ||
gc_len + MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) >=
MDBX_PNL_MAX / 16 * 15)) {
MDBX_PGL_LIMIT / 16 * 15)) {
/* Stop reclaiming to avoid overflow the page list.
* This is a rare case while search for a continuously multi-page region
* in a large database. https://github.com/erthink/libmdbx/issues/123 */
@ -19711,7 +19711,7 @@ __cold int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option,
break;
case MDBX_opt_rp_augment_limit:
if (unlikely(value > MDBX_PNL_MAX))
if (unlikely(value > MDBX_PGL_LIMIT))
return MDBX_EINVAL;
env->me_options.rp_augment_limit = (unsigned)value;
break;

View File

@ -628,9 +628,11 @@ typedef struct MDBX_lockinfo {
#define MAX_MAPSIZE MAX_MAPSIZE64
#define MDBX_READERS_LIMIT \
((65536 - sizeof(MDBX_lockinfo)) / sizeof(MDBX_reader))
#define MDBX_PGL_LIMIT MAX_PAGENO
#else
#define MDBX_READERS_LIMIT 1024
#define MAX_MAPSIZE MAX_MAPSIZE32
#define MDBX_PGL_LIMIT (MAX_MAPSIZE32 / MIN_PAGESIZE)
#endif /* MDBX_WORDBITS */
/*----------------------------------------------------------------------------*/
@ -677,13 +679,9 @@ typedef MDBX_DP *MDBX_DPL;
(MDBX_PNL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
#if MDBX_HUGE_TRANSACTIONS
#define MDBX_PNL_MAX \
((1u << 26) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
#define MDBX_DPL_TXNFULL (MDBX_PNL_MAX / 2)
#define MDBX_DPL_TXNFULL (MDBX_PGL_LIMIT / 8)
#else
#define MDBX_PNL_MAX \
((1u << 24) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
#define MDBX_DPL_TXNFULL (MDBX_PNL_MAX / 4)
#define MDBX_DPL_TXNFULL (MDBX_PGL_LIMIT / 256)
#endif /* MDBX_HUGE_TRANSACTIONS */
#define MDBX_TXL_GRANULATE 32

View File

@ -478,7 +478,7 @@ static int handle_freedb(const uint64_t record_number, const MDBX_val *key,
problem_add("entry", txnid, "wrong idl size", "%" PRIuPTR,
data->iov_len);
size_t number = (data->iov_len >= sizeof(pgno_t)) ? *iptr++ : 0;
if (number < 1 || number > MDBX_PNL_MAX)
if (number < 1 || number > MDBX_PGL_LIMIT)
problem_add("entry", txnid, "wrong idl length", "%" PRIuPTR, number);
else if ((number + 1) * sizeof(pgno_t) > data->iov_len) {
problem_add("entry", txnid, "trimmed idl",