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
|
/** \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
|
* page's numbers for finding a sequence of contiguous pages for large data
|
||||||
* items.
|
* items.
|
||||||
|
* \see MDBX_opt_gc_time_limit
|
||||||
*
|
*
|
||||||
* \details A long values requires allocation of contiguous database pages.
|
* \details A long values requires allocation of contiguous database pages.
|
||||||
* To find such sequences, it may be necessary to accumulate very large lists,
|
* 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
|
* in the \ref MDBX_WRITEMAP mode by clearing ones through file handle before
|
||||||
* touching. */
|
* touching. */
|
||||||
MDBX_opt_prefault_write_enable,
|
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
|
#ifndef __cplusplus
|
||||||
/** \ingroup c_settings */
|
/** \ingroup c_settings */
|
||||||
|
64
src/core.c
64
src/core.c
@ -7674,12 +7674,24 @@ bailout:
|
|||||||
return ret;
|
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,
|
static pgr_t page_alloc_slowpath(const MDBX_cursor *const mc, const size_t num,
|
||||||
uint8_t flags) {
|
uint8_t flags) {
|
||||||
#if MDBX_ENABLE_PROFGC
|
|
||||||
const uint64_t monotime_before = osal_monotime();
|
|
||||||
#endif /* MDBX_ENABLE_PROFGC */
|
|
||||||
|
|
||||||
pgr_t ret;
|
pgr_t ret;
|
||||||
MDBX_txn *const txn = mc->mc_txn;
|
MDBX_txn *const txn = mc->mc_txn;
|
||||||
MDBX_env *const env = txn->mt_env;
|
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,
|
eASSERT(env, pnl_check_allocated(txn->tw.relist,
|
||||||
txn->mt_next_pgno - MDBX_ENABLE_REFUND));
|
txn->mt_next_pgno - MDBX_ENABLE_REFUND));
|
||||||
|
|
||||||
pgno_t pgno = 0;
|
|
||||||
size_t newnext;
|
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 (num > 1) {
|
||||||
#if MDBX_ENABLE_PROFGC
|
#if MDBX_ENABLE_PROFGC
|
||||||
prof->xpages += 1;
|
prof->xpages += 1;
|
||||||
@ -7871,7 +7894,10 @@ next_gc:;
|
|||||||
txn->tw.relist) >= env->me_options.rp_augment_limit) &&
|
txn->tw.relist) >= env->me_options.rp_augment_limit) &&
|
||||||
((/* not a slot-request from gc-update */ num &&
|
((/* not a slot-request from gc-update */ num &&
|
||||||
/* have enough unallocated space */ txn->mt_geo.upper >=
|
/* 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)) {
|
gc_len + MDBX_PNL_GETSIZE(txn->tw.relist) >= MDBX_PGL_LIMIT)) {
|
||||||
/* Stop reclaiming to avoid large/overflow the page list. This is a rare
|
/* Stop reclaiming to avoid large/overflow the page list. This is a rare
|
||||||
* case while search for a continuously multi-page region in a
|
* 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);
|
(size_t)txn->mt_dbs[FREE_DBI].md_entries);
|
||||||
ret.page = NULL;
|
ret.page = NULL;
|
||||||
}
|
}
|
||||||
|
if (num > 1)
|
||||||
|
txn->tw.gc_time_acc += monotime_since_cached(monotime_begin, &now_cache);
|
||||||
} else {
|
} else {
|
||||||
early_exit:
|
early_exit:
|
||||||
DEBUG("return NULL for %zu pages for ALLOC_%s, rc %d", num,
|
DEBUG("return NULL for %zu pages for ALLOC_%s, rc %d", num,
|
||||||
@ -8181,7 +8209,7 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if MDBX_ENABLE_PROFGC
|
#if MDBX_ENABLE_PROFGC
|
||||||
prof->rtime_monotonic += osal_monotime() - monotime_before;
|
prof->rtime_monotonic += osal_monotime() - monotime_begin;
|
||||||
#endif /* MDBX_ENABLE_PROFGC */
|
#endif /* MDBX_ENABLE_PROFGC */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -9352,6 +9380,7 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
|
|||||||
MDBX_PNL_SETSIZE(txn->tw.retired_pages, 0);
|
MDBX_PNL_SETSIZE(txn->tw.retired_pages, 0);
|
||||||
txn->tw.spilled.list = NULL;
|
txn->tw.spilled.list = NULL;
|
||||||
txn->tw.spilled.least_removed = 0;
|
txn->tw.spilled.least_removed = 0;
|
||||||
|
txn->tw.gc_time_acc = 0;
|
||||||
txn->tw.last_reclaimed = 0;
|
txn->tw.last_reclaimed = 0;
|
||||||
if (txn->tw.lifo_reclaimed)
|
if (txn->tw.lifo_reclaimed)
|
||||||
MDBX_PNL_SETSIZE(txn->tw.lifo_reclaimed, 0);
|
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) -
|
= parent->mt_next_pgno) -
|
||||||
MDBX_ENABLE_REFUND));
|
MDBX_ENABLE_REFUND));
|
||||||
|
|
||||||
|
txn->tw.gc_time_acc = parent->tw.gc_time_acc;
|
||||||
txn->tw.last_reclaimed = parent->tw.last_reclaimed;
|
txn->tw.last_reclaimed = parent->tw.last_reclaimed;
|
||||||
if (parent->tw.lifo_reclaimed) {
|
if (parent->tw.lifo_reclaimed) {
|
||||||
txn->tw.lifo_reclaimed = 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);
|
pnl_free(parent->tw.relist);
|
||||||
parent->tw.relist = txn->tw.relist;
|
parent->tw.relist = txn->tw.relist;
|
||||||
txn->tw.relist = NULL;
|
txn->tw.relist = NULL;
|
||||||
|
parent->tw.gc_time_acc = txn->tw.gc_time_acc;
|
||||||
parent->tw.last_reclaimed = txn->tw.last_reclaimed;
|
parent->tw.last_reclaimed = txn->tw.last_reclaimed;
|
||||||
|
|
||||||
parent->mt_geo = txn->mt_geo;
|
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;
|
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_limit:
|
||||||
case MDBX_opt_txn_dp_initial:
|
case MDBX_opt_txn_dp_initial:
|
||||||
if (value == /* default */ UINT64_MAX)
|
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;
|
*pvalue = env->me_options.rp_augment_limit;
|
||||||
break;
|
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:
|
case MDBX_opt_txn_dp_limit:
|
||||||
*pvalue = env->me_options.dp_limit;
|
*pvalue = env->me_options.dp_limit;
|
||||||
break;
|
break;
|
||||||
|
@ -1260,6 +1260,7 @@ struct MDBX_txn {
|
|||||||
size_t writemap_dirty_npages;
|
size_t writemap_dirty_npages;
|
||||||
size_t writemap_spilled_npages;
|
size_t writemap_spilled_npages;
|
||||||
};
|
};
|
||||||
|
uint64_t gc_time_acc;
|
||||||
} tw;
|
} tw;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -1422,6 +1423,7 @@ struct MDBX_env {
|
|||||||
unsigned rp_augment_limit;
|
unsigned rp_augment_limit;
|
||||||
unsigned dp_limit;
|
unsigned dp_limit;
|
||||||
unsigned dp_initial;
|
unsigned dp_initial;
|
||||||
|
uint64_t gc_time_limit;
|
||||||
uint8_t dp_loose_limit;
|
uint8_t dp_loose_limit;
|
||||||
uint8_t spill_max_denominator;
|
uint8_t spill_max_denominator;
|
||||||
uint8_t spill_min_denominator;
|
uint8_t spill_min_denominator;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user