mdbx: добавление опций для subpage: limit, room_threshold, reserve_prereq, reserve_limit.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev)
2024-05-20 14:36:50 +03:00
parent 0e831f42cc
commit 5792eb31eb
7 changed files with 169 additions and 15 deletions

View File

@@ -31,6 +31,26 @@ static bool default_prefer_waf_insteadof_balance(const MDBX_env *env) {
return false;
}
static uint16_t default_subpage_limit(const MDBX_env *env) {
(void)env;
return 65535 /* 100% */;
}
static uint16_t default_subpage_room_threshold(const MDBX_env *env) {
(void)env;
return 0 /* 0% */;
}
static uint16_t default_subpage_reserve_prereq(const MDBX_env *env) {
(void)env;
return 27525 /* 42% */;
}
static uint16_t default_subpage_reserve_limit(const MDBX_env *env) {
(void)env;
return 2753 /* 4.2% */;
}
void env_options_init(MDBX_env *env) {
env->options.rp_augment_limit = MDBX_PNL_INITIAL;
env->options.dp_reserve_limit = MDBX_PNL_INITIAL;
@@ -50,6 +70,11 @@ void env_options_init(MDBX_env *env) {
#endif /* Linux */
MDBX_WRITETHROUGH_THRESHOLD_DEFAULT;
#endif /* Windows */
env->options.subpage.limit = default_subpage_limit(env);
env->options.subpage.room_threshold = default_subpage_room_threshold(env);
env->options.subpage.reserve_prereq = default_subpage_reserve_prereq(env);
env->options.subpage.reserve_limit = default_subpage_reserve_limit(env);
}
void env_options_adjust_defaults(MDBX_env *env) {
@@ -318,6 +343,54 @@ __cold int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option,
env->options.prefer_waf_insteadof_balance = value != 0;
break;
case MDBX_opt_subpage_limit:
if (value == /* default */ UINT64_MAX) {
env->options.subpage.limit = default_subpage_limit(env);
recalculate_subpage_thresholds(env);
} else if (value > 65535)
err = MDBX_EINVAL;
else {
env->options.subpage.limit = (uint16_t)value;
recalculate_subpage_thresholds(env);
}
break;
case MDBX_opt_subpage_room_threshold:
if (value == /* default */ UINT64_MAX) {
env->options.subpage.room_threshold = default_subpage_room_threshold(env);
recalculate_subpage_thresholds(env);
} else if (value > 65535)
err = MDBX_EINVAL;
else {
env->options.subpage.room_threshold = (uint16_t)value;
recalculate_subpage_thresholds(env);
}
break;
case MDBX_opt_subpage_reserve_prereq:
if (value == /* default */ UINT64_MAX) {
env->options.subpage.reserve_prereq = default_subpage_reserve_prereq(env);
recalculate_subpage_thresholds(env);
} else if (value > 65535)
err = MDBX_EINVAL;
else {
env->options.subpage.reserve_prereq = (uint16_t)value;
recalculate_subpage_thresholds(env);
}
break;
case MDBX_opt_subpage_reserve_limit:
if (value == /* default */ UINT64_MAX) {
env->options.subpage.reserve_limit = default_subpage_reserve_limit(env);
recalculate_subpage_thresholds(env);
} else if (value > 65535)
err = MDBX_EINVAL;
else {
env->options.subpage.reserve_limit = (uint16_t)value;
recalculate_subpage_thresholds(env);
}
break;
default:
return MDBX_EINVAL;
}
@@ -411,6 +484,22 @@ __cold int mdbx_env_get_option(const MDBX_env *env, const MDBX_option_t option,
*pvalue = env->options.prefer_waf_insteadof_balance;
break;
case MDBX_opt_subpage_limit:
*pvalue = env->options.subpage.limit;
break;
case MDBX_opt_subpage_room_threshold:
*pvalue = env->options.subpage.room_threshold;
break;
case MDBX_opt_subpage_reserve_prereq:
*pvalue = env->options.subpage.reserve_prereq;
break;
case MDBX_opt_subpage_reserve_limit:
*pvalue = env->options.subpage.reserve_limit;
break;
default:
return MDBX_EINVAL;
}

View File

@@ -58,15 +58,7 @@ __cold unsigned env_setup_pagesize(MDBX_env *env, const size_t pagesize) {
eASSERT(env, pgno2bytes(env, 1) == pagesize);
eASSERT(env, bytes2pgno(env, pagesize + pagesize) == 2);
recalculate_merge_thresholds(env);
/* TODO: recalculate me_subpage_xyz values from MDBX_opt_subpage_xyz. */
env->subpage_limit = env->leaf_nodemax - NODESIZE;
env->subpage_room_threshold = 0;
env->subpage_reserve_prereq = env->leaf_nodemax;
env->subpage_reserve_limit = env->subpage_limit / 42;
eASSERT(env, env->subpage_reserve_prereq >
env->subpage_room_threshold + env->subpage_reserve_limit);
eASSERT(env, env->leaf_nodemax >= env->subpage_limit + NODESIZE);
recalculate_subpage_thresholds(env);
const pgno_t max_pgno = bytes2pgno(env, MAX_MAPSIZE);
if (!env->options.flags.non_auto.dp_limit) {

View File

@@ -408,6 +408,13 @@ struct MDBX_env {
bool prefault_write;
bool prefer_waf_insteadof_balance; /* Strive to minimize WAF instead of
balancing pages fullment */
struct {
uint16_t limit;
uint16_t room_threshold;
uint16_t reserve_prereq;
uint16_t reserve_limit;
} subpage;
union {
unsigned all;
/* tracks options with non-auto values but tuned by user */

View File

@@ -752,12 +752,35 @@ __hot int __must_check_result page_dirty(MDBX_txn *txn, page_t *mp,
return MDBX_SUCCESS;
}
size_t page_subleaf2_reserve(const MDBX_env *const env, size_t host_page_room,
void recalculate_subpage_thresholds(MDBX_env *env) {
size_t whole = env->leaf_nodemax - NODESIZE;
env->subpage_limit = (whole * env->options.subpage.limit + 32767) >> 16;
whole = env->subpage_limit;
env->subpage_reserve_limit =
(whole * env->options.subpage.reserve_limit + 32767) >> 16;
eASSERT(env, env->leaf_nodemax >= env->subpage_limit + NODESIZE);
eASSERT(env, env->subpage_limit >= env->subpage_reserve_limit);
whole = env->leaf_nodemax;
env->subpage_room_threshold =
(whole * env->options.subpage.room_threshold + 32767) >> 16;
env->subpage_reserve_prereq =
(whole * env->options.subpage.reserve_prereq + 32767) >> 16;
if (env->subpage_room_threshold + env->subpage_reserve_limit >
(intptr_t)page_space(env))
env->subpage_reserve_prereq = page_space(env);
else if (env->subpage_reserve_prereq <
env->subpage_room_threshold + env->subpage_reserve_limit)
env->subpage_reserve_prereq =
env->subpage_room_threshold + env->subpage_reserve_limit;
eASSERT(env, env->subpage_reserve_prereq >
env->subpage_room_threshold + env->subpage_reserve_limit);
}
size_t page_subleaf2_reserve(const MDBX_env *env, size_t host_page_room,
size_t subpage_len, size_t item_len) {
eASSERT(env, (subpage_len & 1) == 0);
eASSERT(env, env->subpage_reserve_prereq > env->subpage_room_threshold +
env->subpage_reserve_limit &&
env->leaf_nodemax >= env->subpage_limit + NODESIZE);
eASSERT(env, env->leaf_nodemax >= env->subpage_limit + NODESIZE);
size_t reserve = 0;
for (size_t n = 0;
n < 5 && reserve + item_len <= env->subpage_reserve_limit &&

View File

@@ -171,7 +171,7 @@ static inline void page_wash(MDBX_txn *txn, size_t di, page_t *const mp,
pgno2bytes(txn->env, npages) - PAGEHDRSZ);
}
MDBX_INTERNAL size_t page_subleaf2_reserve(const MDBX_env *const env,
MDBX_INTERNAL size_t page_subleaf2_reserve(const MDBX_env *env,
size_t host_page_room,
size_t subpage_len, size_t item_len);

View File

@@ -97,6 +97,7 @@ MDBX_INTERNAL int __must_check_result tree_rebalance(MDBX_cursor *mc);
MDBX_INTERNAL int __must_check_result tree_propagate_key(MDBX_cursor *mc,
const MDBX_val *key);
MDBX_INTERNAL void recalculate_merge_thresholds(MDBX_env *env);
MDBX_INTERNAL void recalculate_subpage_thresholds(MDBX_env *env);
/* subdb.c */
MDBX_INTERNAL int __must_check_result sdb_fetch(MDBX_txn *txn, size_t dbi);