mirror of
https://github.com/isar/libmdbx.git
synced 2025-04-28 07:42:26 +08:00
mdbx: добавление MDBX_opt_gc_time_limit.
This commit is contained in:
parent
508cf83c32
commit
eeec44f56d
28
mdbx.h
28
mdbx.h
@ -2133,6 +2133,7 @@ enum MDBX_option_t {
|
||||
/** \brief Controls the in-process limit to grow a list of reclaimed/recycled
|
||||
* page's numbers for finding a sequence of contiguous pages for large data
|
||||
* items.
|
||||
* \see MDBX_opt_gc_time_limit
|
||||
*
|
||||
* \details A long values requires allocation of contiguous database pages.
|
||||
* To find such sequences, it may be necessary to accumulate very large lists,
|
||||
@ -2293,6 +2294,33 @@ enum MDBX_option_t {
|
||||
* in the \ref MDBX_WRITEMAP mode by clearing ones through file handle before
|
||||
* touching. */
|
||||
MDBX_opt_prefault_write_enable,
|
||||
|
||||
/** \brief Controls the in-process spending time limit of searching
|
||||
* consecutive pages inside GC.
|
||||
* \see MDBX_opt_rp_augment_limit
|
||||
*
|
||||
* \details Задаёт ограничение времени в 1/65536 долях секунды, которое может
|
||||
* быть потрачено в ходе пишущей транзакции на поиск последовательностей
|
||||
* страниц внутри GC/freelist после достижения ограничения задаваемого опцией
|
||||
* \ref MDBX_opt_rp_augment_limit. Контроль по времени не выполняется при
|
||||
* поиске/выделении одиночных страниц и выделении страниц под нужды GC (при
|
||||
* обновлении GC в ходе фиксации транзакции).
|
||||
*
|
||||
* Задаваемый лимит времени исчисляется по "настенным часам" и контролируется
|
||||
* в рамках транзакции, наследуется для вложенных транзакций и с
|
||||
* аккумулированием в родительской при их фиксации. Контроль по времени
|
||||
* производится только при достижении ограничения задаваемого опцией \ref
|
||||
* MDBX_opt_rp_augment_limit. Это позволяет гибко управлять поведением
|
||||
* используя обе опции.
|
||||
*
|
||||
* По умолчанию ограничение устанавливается в 0, что приводит к
|
||||
* незамедлительной остановке поиска в GC при достижении \ref
|
||||
* MDBX_opt_rp_augment_limit во внутреннем состоянии транзакции и
|
||||
* соответствует поведению до появления опции `MDBX_opt_gc_time_limit`.
|
||||
* С другой стороны, при минимальном значении (включая 0)
|
||||
* `MDBX_opt_rp_augment_limit` переработка GC будет ограничиваться
|
||||
* преимущественно затраченным временем. */
|
||||
MDBX_opt_gc_time_limit
|
||||
};
|
||||
#ifndef __cplusplus
|
||||
/** \ingroup c_settings */
|
||||
|
64
src/core.c
64
src/core.c
@ -7674,12 +7674,24 @@ bailout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct monotime_cache {
|
||||
uint64_t value;
|
||||
int expire_countdown;
|
||||
};
|
||||
|
||||
static __inline uint64_t monotime_since_cached(uint64_t begin_timestamp,
|
||||
struct monotime_cache *cache) {
|
||||
if (cache->expire_countdown)
|
||||
cache->expire_countdown -= 1;
|
||||
else {
|
||||
cache->value = osal_monotime();
|
||||
cache->expire_countdown = 42 / 3;
|
||||
}
|
||||
return cache->value - begin_timestamp;
|
||||
}
|
||||
|
||||
static pgr_t page_alloc_slowpath(const MDBX_cursor *const mc, const size_t num,
|
||||
uint8_t flags) {
|
||||
#if MDBX_ENABLE_PROFGC
|
||||
const uint64_t monotime_before = osal_monotime();
|
||||
#endif /* MDBX_ENABLE_PROFGC */
|
||||
|
||||
pgr_t ret;
|
||||
MDBX_txn *const txn = mc->mc_txn;
|
||||
MDBX_env *const env = txn->mt_env;
|
||||
@ -7694,8 +7706,19 @@ static pgr_t page_alloc_slowpath(const MDBX_cursor *const mc, const size_t num,
|
||||
eASSERT(env, pnl_check_allocated(txn->tw.relist,
|
||||
txn->mt_next_pgno - MDBX_ENABLE_REFUND));
|
||||
|
||||
pgno_t pgno = 0;
|
||||
size_t newnext;
|
||||
const uint64_t monotime_begin =
|
||||
(MDBX_ENABLE_PROFGC || (num > 1 && env->me_options.gc_time_limit))
|
||||
? osal_monotime()
|
||||
: 0;
|
||||
struct monotime_cache now_cache;
|
||||
now_cache.expire_countdown =
|
||||
1 /* старт с 1 позволяет избавиться как от лишних системных вызовов когда
|
||||
лимит времени задан нулевой или уже исчерпан, так и от подсчета
|
||||
времени при не-достижении rp_augment_limit */
|
||||
;
|
||||
now_cache.value = monotime_begin;
|
||||
pgno_t pgno = 0;
|
||||
if (num > 1) {
|
||||
#if MDBX_ENABLE_PROFGC
|
||||
prof->xpages += 1;
|
||||
@ -7871,7 +7894,10 @@ next_gc:;
|
||||
txn->tw.relist) >= env->me_options.rp_augment_limit) &&
|
||||
((/* not a slot-request from gc-update */ num &&
|
||||
/* have enough unallocated space */ txn->mt_geo.upper >=
|
||||
txn->mt_next_pgno + num) ||
|
||||
txn->mt_next_pgno + num &&
|
||||
monotime_since_cached(monotime_begin, &now_cache) +
|
||||
txn->tw.gc_time_acc >=
|
||||
env->me_options.gc_time_limit) ||
|
||||
gc_len + MDBX_PNL_GETSIZE(txn->tw.relist) >= MDBX_PGL_LIMIT)) {
|
||||
/* Stop reclaiming to avoid large/overflow the page list. This is a rare
|
||||
* case while search for a continuously multi-page region in a
|
||||
@ -8173,6 +8199,8 @@ done:
|
||||
(size_t)txn->mt_dbs[FREE_DBI].md_entries);
|
||||
ret.page = NULL;
|
||||
}
|
||||
if (num > 1)
|
||||
txn->tw.gc_time_acc += monotime_since_cached(monotime_begin, &now_cache);
|
||||
} else {
|
||||
early_exit:
|
||||
DEBUG("return NULL for %zu pages for ALLOC_%s, rc %d", num,
|
||||
@ -8181,7 +8209,7 @@ done:
|
||||
}
|
||||
|
||||
#if MDBX_ENABLE_PROFGC
|
||||
prof->rtime_monotonic += osal_monotime() - monotime_before;
|
||||
prof->rtime_monotonic += osal_monotime() - monotime_begin;
|
||||
#endif /* MDBX_ENABLE_PROFGC */
|
||||
return ret;
|
||||
}
|
||||
@ -9352,6 +9380,7 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
|
||||
MDBX_PNL_SETSIZE(txn->tw.retired_pages, 0);
|
||||
txn->tw.spilled.list = NULL;
|
||||
txn->tw.spilled.least_removed = 0;
|
||||
txn->tw.gc_time_acc = 0;
|
||||
txn->tw.last_reclaimed = 0;
|
||||
if (txn->tw.lifo_reclaimed)
|
||||
MDBX_PNL_SETSIZE(txn->tw.lifo_reclaimed, 0);
|
||||
@ -9800,6 +9829,7 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags,
|
||||
= parent->mt_next_pgno) -
|
||||
MDBX_ENABLE_REFUND));
|
||||
|
||||
txn->tw.gc_time_acc = parent->tw.gc_time_acc;
|
||||
txn->tw.last_reclaimed = parent->tw.last_reclaimed;
|
||||
if (parent->tw.lifo_reclaimed) {
|
||||
txn->tw.lifo_reclaimed = parent->tw.lifo_reclaimed;
|
||||
@ -12037,6 +12067,7 @@ int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency) {
|
||||
pnl_free(parent->tw.relist);
|
||||
parent->tw.relist = txn->tw.relist;
|
||||
txn->tw.relist = NULL;
|
||||
parent->tw.gc_time_acc = txn->tw.gc_time_acc;
|
||||
parent->tw.last_reclaimed = txn->tw.last_reclaimed;
|
||||
|
||||
parent->mt_geo = txn->mt_geo;
|
||||
@ -25875,6 +25906,21 @@ __cold int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option,
|
||||
}
|
||||
break;
|
||||
|
||||
case MDBX_opt_gc_time_limit:
|
||||
if (value == /* default */ UINT64_MAX)
|
||||
value = 0;
|
||||
if (unlikely(value > UINT32_MAX))
|
||||
return MDBX_EINVAL;
|
||||
if (unlikely(env->me_flags & MDBX_RDONLY))
|
||||
return MDBX_EACCESS;
|
||||
value = osal_16dot16_to_monotime((uint32_t)value);
|
||||
if (value != env->me_options.gc_time_limit) {
|
||||
if (env->me_txn && env->me_txn0->mt_owner != osal_thread_self())
|
||||
return MDBX_EPERM;
|
||||
env->me_options.gc_time_limit = value;
|
||||
}
|
||||
break;
|
||||
|
||||
case MDBX_opt_txn_dp_limit:
|
||||
case MDBX_opt_txn_dp_initial:
|
||||
if (value == /* default */ UINT64_MAX)
|
||||
@ -26027,6 +26073,10 @@ __cold int mdbx_env_get_option(const MDBX_env *env, const MDBX_option_t option,
|
||||
*pvalue = env->me_options.rp_augment_limit;
|
||||
break;
|
||||
|
||||
case MDBX_opt_gc_time_limit:
|
||||
*pvalue = osal_monotime_to_16dot16(env->me_options.gc_time_limit);
|
||||
break;
|
||||
|
||||
case MDBX_opt_txn_dp_limit:
|
||||
*pvalue = env->me_options.dp_limit;
|
||||
break;
|
||||
|
@ -1260,6 +1260,7 @@ struct MDBX_txn {
|
||||
size_t writemap_dirty_npages;
|
||||
size_t writemap_spilled_npages;
|
||||
};
|
||||
uint64_t gc_time_acc;
|
||||
} tw;
|
||||
};
|
||||
};
|
||||
@ -1422,6 +1423,7 @@ struct MDBX_env {
|
||||
unsigned rp_augment_limit;
|
||||
unsigned dp_limit;
|
||||
unsigned dp_initial;
|
||||
uint64_t gc_time_limit;
|
||||
uint8_t dp_loose_limit;
|
||||
uint8_t spill_max_denominator;
|
||||
uint8_t spill_min_denominator;
|
||||
|
Loading…
x
Reference in New Issue
Block a user