mirror of
https://github.com/isar/libmdbx.git
synced 2025-02-08 15:40:51 +08:00
mdbx: introduce MDBX_PGL_LIMIT
.
Change-Id: Ifab1156ec22fb0908284298393f52c09c0731829
This commit is contained in:
parent
4cd08f0ef9
commit
0b62453f6d
1
.github/actions/spelling/expect.txt
vendored
1
.github/actions/spelling/expect.txt
vendored
@ -1183,6 +1183,7 @@ perror
|
|||||||
PFILE
|
PFILE
|
||||||
pflags
|
pflags
|
||||||
pgcount
|
pgcount
|
||||||
|
PGL
|
||||||
pglist
|
pglist
|
||||||
pgno
|
pgno
|
||||||
pgnumber
|
pgnumber
|
||||||
|
42
src/core.c
42
src/core.c
@ -398,10 +398,11 @@ __cold intptr_t mdbx_limits_valsize_max(intptr_t pagesize,
|
|||||||
const unsigned page_ln2 = log2n(pagesize);
|
const unsigned page_ln2 = log2n(pagesize);
|
||||||
const size_t hard = 0x7FF00000ul;
|
const size_t hard = 0x7FF00000ul;
|
||||||
const size_t hard_pages = hard >> page_ln2;
|
const size_t hard_pages = hard >> page_ln2;
|
||||||
const size_t limit = (hard_pages < MDBX_DPL_TXNFULL / 3)
|
STATIC_ASSERT(MDBX_PGL_LIMIT <= MAX_PAGENO);
|
||||||
? hard
|
const size_t pages_limit = MDBX_PGL_LIMIT / 4;
|
||||||
: ((size_t)MDBX_DPL_TXNFULL / 3 << page_ln2);
|
const size_t limit =
|
||||||
return (limit < MAX_MAPSIZE) ? limit / 2 : MAX_MAPSIZE / 2;
|
(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.
|
/* 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) {
|
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 =
|
size_t bytes =
|
||||||
ceil_powerof2(MDBX_ASSUME_MALLOC_OVERHEAD + sizeof(pgno_t) * (size + 2),
|
ceil_powerof2(MDBX_ASSUME_MALLOC_OVERHEAD + sizeof(pgno_t) * (size + 2),
|
||||||
MDBX_PNL_GRANULATE * sizeof(pgno_t)) -
|
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) {
|
static __always_inline pgno_t bytes2pnl(const size_t bytes) {
|
||||||
size_t size = bytes / sizeof(pgno_t);
|
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;
|
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 */
|
/* Shrink the PNL to the default size if it has grown larger */
|
||||||
static void mdbx_pnl_shrink(MDBX_PNL *ppl) {
|
static void mdbx_pnl_shrink(MDBX_PNL *ppl) {
|
||||||
assert(bytes2pnl(pnl2bytes(MDBX_PNL_INITIAL)) == MDBX_PNL_INITIAL);
|
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_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl));
|
||||||
MDBX_PNL_SIZE(*ppl) = 0;
|
MDBX_PNL_SIZE(*ppl) = 0;
|
||||||
if (unlikely(MDBX_PNL_ALLOCLEN(*ppl) >
|
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 */
|
/* Grow the PNL to the size growed to at least given size */
|
||||||
static int mdbx_pnl_reserve(MDBX_PNL *ppl, const size_t wanna) {
|
static int mdbx_pnl_reserve(MDBX_PNL *ppl, const size_t wanna) {
|
||||||
const size_t allocated = MDBX_PNL_ALLOCLEN(*ppl);
|
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));
|
MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl));
|
||||||
if (likely(allocated >= wanna))
|
if (likely(allocated >= wanna))
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
|
|
||||||
if (unlikely(wanna > /* paranoia */ MDBX_PNL_MAX))
|
if (unlikely(wanna > /* paranoia */ MDBX_PGL_LIMIT))
|
||||||
return MDBX_TXN_FULL;
|
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
|
? wanna + wanna - allocated
|
||||||
: MDBX_PNL_MAX;
|
: MDBX_PGL_LIMIT;
|
||||||
size_t bytes = pnl2bytes(size);
|
size_t bytes = pnl2bytes(size);
|
||||||
MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes);
|
MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes);
|
||||||
if (likely(pl)) {
|
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 */
|
/* Make room for num additional elements in an PNL */
|
||||||
static __always_inline int __must_check_result mdbx_pnl_need(MDBX_PNL *ppl,
|
static __always_inline int __must_check_result mdbx_pnl_need(MDBX_PNL *ppl,
|
||||||
size_t num) {
|
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));
|
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;
|
const size_t wanna = MDBX_PNL_SIZE(*ppl) + num;
|
||||||
return likely(MDBX_PNL_ALLOCLEN(*ppl) >= wanna)
|
return likely(MDBX_PNL_ALLOCLEN(*ppl) >= wanna)
|
||||||
? MDBX_SUCCESS
|
? 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))) {
|
if (likely(MDBX_PNL_SIZE(pl))) {
|
||||||
assert(MDBX_PNL_LEAST(pl) >= MIN_PAGENO);
|
assert(MDBX_PNL_LEAST(pl) >= MIN_PAGENO);
|
||||||
assert(MDBX_PNL_MOST(pl) < limit);
|
assert(MDBX_PNL_MOST(pl) < limit);
|
||||||
assert(MDBX_PNL_SIZE(pl) <= MDBX_PNL_MAX);
|
assert(MDBX_PNL_SIZE(pl) <= MDBX_PGL_LIMIT);
|
||||||
if (unlikely(MDBX_PNL_SIZE(pl) > MDBX_PNL_MAX * 3 / 2))
|
if (unlikely(MDBX_PNL_SIZE(pl) > MDBX_PGL_LIMIT))
|
||||||
return false;
|
return false;
|
||||||
if (unlikely(MDBX_PNL_LEAST(pl) < MIN_PAGENO))
|
if (unlikely(MDBX_PNL_LEAST(pl) < MIN_PAGENO))
|
||||||
return false;
|
return false;
|
||||||
@ -2945,7 +2946,7 @@ static __always_inline int __must_check_result mdbx_txl_need(MDBX_TXL *ptl,
|
|||||||
size_t num) {
|
size_t num) {
|
||||||
assert(MDBX_PNL_SIZE(*ptl) <= MDBX_TXL_MAX &&
|
assert(MDBX_PNL_SIZE(*ptl) <= MDBX_TXL_MAX &&
|
||||||
MDBX_PNL_ALLOCLEN(*ptl) >= MDBX_PNL_SIZE(*ptl));
|
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;
|
const size_t wanna = (size_t)MDBX_PNL_SIZE(*ptl) + num;
|
||||||
return likely(MDBX_PNL_ALLOCLEN(*ptl) >= wanna)
|
return likely(MDBX_PNL_ALLOCLEN(*ptl) >= wanna)
|
||||||
? MDBX_SUCCESS
|
? 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)
|
#define DP_SORT_CMP(first, last) ((first).pgno < (last).pgno)
|
||||||
SORT_IMPL(dp_sort, false, MDBX_DP, DP_SORT_CMP)
|
SORT_IMPL(dp_sort, false, MDBX_DP, DP_SORT_CMP)
|
||||||
static __always_inline MDBX_DPL mdbx_dpl_sort(MDBX_DPL dl) {
|
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);
|
assert(dl->sorted <= dl->length);
|
||||||
if (dl->sorted != dl->length) {
|
if (dl->sorted != dl->length) {
|
||||||
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
|
static __always_inline int __must_check_result
|
||||||
mdbx_dpl_append(MDBX_DPL dl, pgno_t pgno, MDBX_page *page) {
|
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()) {
|
if (mdbx_audit_enabled()) {
|
||||||
for (unsigned i = dl->length; i > 0; --i) {
|
for (unsigned i = dl->length; i > 0; --i) {
|
||||||
assert(dl[i].pgno != pgno);
|
assert(dl[i].pgno != pgno);
|
||||||
@ -5277,12 +5278,11 @@ skip_cache:
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
const unsigned gc_len = MDBX_PNL_SIZE(gc_pnl);
|
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) >
|
if (unlikely(gc_len + MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) >
|
||||||
env->me_options.rp_augment_limit) &&
|
env->me_options.rp_augment_limit) &&
|
||||||
(pgno_add(txn->mt_next_pgno, num) <= txn->mt_geo.upper ||
|
(pgno_add(txn->mt_next_pgno, num) <= txn->mt_geo.upper ||
|
||||||
gc_len + MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) >=
|
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.
|
/* Stop reclaiming to avoid overflow the page list.
|
||||||
* This is a rare case while search for a continuously multi-page region
|
* This is a rare case while search for a continuously multi-page region
|
||||||
* in a large database. https://github.com/erthink/libmdbx/issues/123 */
|
* 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;
|
break;
|
||||||
|
|
||||||
case MDBX_opt_rp_augment_limit:
|
case MDBX_opt_rp_augment_limit:
|
||||||
if (unlikely(value > MDBX_PNL_MAX))
|
if (unlikely(value > MDBX_PGL_LIMIT))
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
env->me_options.rp_augment_limit = (unsigned)value;
|
env->me_options.rp_augment_limit = (unsigned)value;
|
||||||
break;
|
break;
|
||||||
|
@ -628,9 +628,11 @@ typedef struct MDBX_lockinfo {
|
|||||||
#define MAX_MAPSIZE MAX_MAPSIZE64
|
#define MAX_MAPSIZE MAX_MAPSIZE64
|
||||||
#define MDBX_READERS_LIMIT \
|
#define MDBX_READERS_LIMIT \
|
||||||
((65536 - sizeof(MDBX_lockinfo)) / sizeof(MDBX_reader))
|
((65536 - sizeof(MDBX_lockinfo)) / sizeof(MDBX_reader))
|
||||||
|
#define MDBX_PGL_LIMIT MAX_PAGENO
|
||||||
#else
|
#else
|
||||||
#define MDBX_READERS_LIMIT 1024
|
#define MDBX_READERS_LIMIT 1024
|
||||||
#define MAX_MAPSIZE MAX_MAPSIZE32
|
#define MAX_MAPSIZE MAX_MAPSIZE32
|
||||||
|
#define MDBX_PGL_LIMIT (MAX_MAPSIZE32 / MIN_PAGESIZE)
|
||||||
#endif /* MDBX_WORDBITS */
|
#endif /* MDBX_WORDBITS */
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
@ -677,13 +679,9 @@ typedef MDBX_DP *MDBX_DPL;
|
|||||||
(MDBX_PNL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
|
(MDBX_PNL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
|
||||||
|
|
||||||
#if MDBX_HUGE_TRANSACTIONS
|
#if MDBX_HUGE_TRANSACTIONS
|
||||||
#define MDBX_PNL_MAX \
|
#define MDBX_DPL_TXNFULL (MDBX_PGL_LIMIT / 8)
|
||||||
((1u << 26) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
|
|
||||||
#define MDBX_DPL_TXNFULL (MDBX_PNL_MAX / 2)
|
|
||||||
#else
|
#else
|
||||||
#define MDBX_PNL_MAX \
|
#define MDBX_DPL_TXNFULL (MDBX_PGL_LIMIT / 256)
|
||||||
((1u << 24) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
|
|
||||||
#define MDBX_DPL_TXNFULL (MDBX_PNL_MAX / 4)
|
|
||||||
#endif /* MDBX_HUGE_TRANSACTIONS */
|
#endif /* MDBX_HUGE_TRANSACTIONS */
|
||||||
|
|
||||||
#define MDBX_TXL_GRANULATE 32
|
#define MDBX_TXL_GRANULATE 32
|
||||||
|
@ -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,
|
problem_add("entry", txnid, "wrong idl size", "%" PRIuPTR,
|
||||||
data->iov_len);
|
data->iov_len);
|
||||||
size_t number = (data->iov_len >= sizeof(pgno_t)) ? *iptr++ : 0;
|
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);
|
problem_add("entry", txnid, "wrong idl length", "%" PRIuPTR, number);
|
||||||
else if ((number + 1) * sizeof(pgno_t) > data->iov_len) {
|
else if ((number + 1) * sizeof(pgno_t) > data->iov_len) {
|
||||||
problem_add("entry", txnid, "trimmed idl",
|
problem_add("entry", txnid, "trimmed idl",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user