mirror of
https://github.com/isar/libmdbx.git
synced 2025-06-26 15:02:37 +08:00
mdbx: add MDBX_opt_spill_max_denominator
and MDBX_opt_spill_min_denominator
runtime options.
More for https://github.com/erthink/libmdbx/issues/128 Change-Id: I6b1b00e30ac11e9c2e3d3d3a29cc73079b41d539
This commit is contained in:
parent
0166071ec9
commit
56aaad03bc
32
mdbx.h
32
mdbx.h
@ -1885,6 +1885,38 @@ enum MDBX_option_t {
|
|||||||
/** \brief Controls the in-process initial allocation size for dirty pages
|
/** \brief Controls the in-process initial allocation size for dirty pages
|
||||||
* list of a write transaction. Default is 1024. */
|
* list of a write transaction. Default is 1024. */
|
||||||
MDBX_opt_txn_dp_initial,
|
MDBX_opt_txn_dp_initial,
|
||||||
|
|
||||||
|
/** \brief Controls the in-process how maximal part of the dirty pages may be
|
||||||
|
* spilled when necessary.
|
||||||
|
*
|
||||||
|
* \details The `MDBX_opt_spill_max_denominator` defines the denominator for
|
||||||
|
* limiting from the top for part of the current dirty pages may be spilled
|
||||||
|
* when the free room for a new dirty pages (i.e. distance to the
|
||||||
|
* `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested
|
||||||
|
* operation.
|
||||||
|
* Exactly `max_pages_to_spill = dirty_pages - dirty_pages / N`,
|
||||||
|
* where `N` is the value set by `MDBX_opt_spill_max_denominator`.
|
||||||
|
*
|
||||||
|
* Should be in the range 0..255, where zero means no limit, i.e. all dirty
|
||||||
|
* pages could be spilled. Default is 8, i.e. no more than 7/8 of the current
|
||||||
|
* dirty pages may be spilled when reached the condition described above. */
|
||||||
|
MDBX_opt_spill_max_denominator,
|
||||||
|
|
||||||
|
/** \brief Controls the in-process how minimal part of the dirty pages should
|
||||||
|
* be spilled when necessary.
|
||||||
|
*
|
||||||
|
* \details The `MDBX_opt_spill_min_denominator` defines the denominator for
|
||||||
|
* limiting from the bottom for part of the current dirty pages should be
|
||||||
|
* spilled when the free room for a new dirty pages (i.e. distance to the
|
||||||
|
* `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested
|
||||||
|
* operation.
|
||||||
|
* Exactly `min_pages_to_spill = dirty_pages / N`,
|
||||||
|
* where `N` is the value set by `MDBX_opt_spill_min_denominator`.
|
||||||
|
*
|
||||||
|
* Should be in the range 0..255, where zero means no restriction at the
|
||||||
|
* bottom. Default is 8, i.e. at least the 1/8 of the current dirty pages
|
||||||
|
* should be spilled when reached the condition described above. */
|
||||||
|
MDBX_opt_spill_min_denominator,
|
||||||
};
|
};
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
/** \ingroup c_settings */
|
/** \ingroup c_settings */
|
||||||
|
44
src/core.c
44
src/core.c
@ -4532,21 +4532,33 @@ static void mdbx_txn_xkeep(MDBX_txn *txn, MDBX_cursor *m0,
|
|||||||
* the child hasn't committed yet, and we'd have no way to undo it if
|
* the child hasn't committed yet, and we'd have no way to undo it if
|
||||||
* the child aborted. */
|
* the child aborted. */
|
||||||
static int mdbx_txn_spill(MDBX_txn *txn, MDBX_cursor *m0, unsigned need) {
|
static int mdbx_txn_spill(MDBX_txn *txn, MDBX_cursor *m0, unsigned need) {
|
||||||
|
#ifndef MDBX_DEBUG_SPILLING
|
||||||
if (likely(txn->tw.dirtyroom > need))
|
if (likely(txn->tw.dirtyroom > need))
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
|
|
||||||
const unsigned spill_min =
|
|
||||||
(txn->tw.dirtylist->length / /* TODO: options */ 8);
|
|
||||||
const unsigned spill_max =
|
|
||||||
(txn->tw.dirtylist->length / /* TODO: options */ 1);
|
|
||||||
unsigned spill = need - txn->tw.dirtyroom;
|
unsigned spill = need - txn->tw.dirtyroom;
|
||||||
spill = (spill < spill_max) ? spill : spill_max;
|
#else
|
||||||
|
/* spill at least one page if defined MDBX_DEBUG_SPILLING */
|
||||||
|
unsigned spill = (need > txn->tw.dirtyroom) ? need - txn->tw.dirtyroom : 1;
|
||||||
|
#endif /* MDBX_DEBUG_SPILLING */
|
||||||
|
|
||||||
|
const unsigned dirty = txn->tw.dirtylist->length;
|
||||||
|
const unsigned spill_min =
|
||||||
|
txn->mt_env->me_options.spill_min_denominator
|
||||||
|
? dirty / txn->mt_env->me_options.spill_min_denominator
|
||||||
|
: 0;
|
||||||
|
const unsigned spill_max =
|
||||||
|
dirty - (txn->mt_env->me_options.spill_max_denominator
|
||||||
|
? dirty / txn->mt_env->me_options.spill_max_denominator
|
||||||
|
: 0);
|
||||||
spill = (spill > spill_min) ? spill : spill_min;
|
spill = (spill > spill_min) ? spill : spill_min;
|
||||||
|
spill = (spill < spill_max) ? spill : spill_max;
|
||||||
if (!spill)
|
if (!spill)
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
|
|
||||||
mdbx_notice("spilling %u dirty-entries (have %u dirty-room, need %u)", spill,
|
mdbx_notice("spilling %u dirty-entries (have %u dirty-room, need %u)", spill,
|
||||||
txn->tw.dirtyroom, need);
|
txn->tw.dirtyroom, need);
|
||||||
|
mdbx_tassert(txn, txn->tw.dirtylist->length >= spill);
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
if (!txn->tw.spill_pages) {
|
if (!txn->tw.spill_pages) {
|
||||||
txn->tw.spill_least_removed = INT_MAX;
|
txn->tw.spill_least_removed = INT_MAX;
|
||||||
@ -9908,6 +9920,8 @@ __cold int mdbx_env_create(MDBX_env **penv) {
|
|||||||
env->me_options.dp_initial = MDBX_PNL_INITIAL;
|
env->me_options.dp_initial = MDBX_PNL_INITIAL;
|
||||||
if (env->me_options.dp_initial > env->me_options.dp_limit)
|
if (env->me_options.dp_initial > env->me_options.dp_limit)
|
||||||
env->me_options.dp_initial = env->me_options.dp_limit;
|
env->me_options.dp_initial = env->me_options.dp_limit;
|
||||||
|
env->me_options.spill_max_denominator = 8;
|
||||||
|
env->me_options.spill_min_denominator = 8;
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
const size_t os_psize = mdbx_syspagesize();
|
const size_t os_psize = mdbx_syspagesize();
|
||||||
@ -20438,6 +20452,17 @@ __cold int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MDBX_opt_spill_max_denominator:
|
||||||
|
if (unlikely(value > 255))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
env->me_options.spill_max_denominator = (uint8_t)value;
|
||||||
|
break;
|
||||||
|
case MDBX_opt_spill_min_denominator:
|
||||||
|
if (unlikely(value > 255))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
env->me_options.spill_min_denominator = (uint8_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
}
|
}
|
||||||
@ -20491,6 +20516,13 @@ __cold int mdbx_env_get_option(const MDBX_env *env, const MDBX_option_t option,
|
|||||||
*value = env->me_options.dp_initial;
|
*value = env->me_options.dp_initial;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MDBX_opt_spill_max_denominator:
|
||||||
|
*value = env->me_options.spill_max_denominator;
|
||||||
|
break;
|
||||||
|
case MDBX_opt_spill_min_denominator:
|
||||||
|
*value = env->me_options.spill_min_denominator;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -983,6 +983,8 @@ struct MDBX_env {
|
|||||||
unsigned rp_augment_limit;
|
unsigned rp_augment_limit;
|
||||||
unsigned dp_limit;
|
unsigned dp_limit;
|
||||||
unsigned dp_initial;
|
unsigned dp_initial;
|
||||||
|
uint8_t spill_max_denominator;
|
||||||
|
uint8_t spill_min_denominator;
|
||||||
} me_options;
|
} me_options;
|
||||||
struct {
|
struct {
|
||||||
#if MDBX_LOCKING > 0
|
#if MDBX_LOCKING > 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user