mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-29 23:19:20 +08:00
mdbx: statistics of page operations.
Related to https://github.com/erthink/libmdbx/issues/186 Change-Id: Ia00e6e0df9a65f880517ca33e7f444a0526b96e1
This commit is contained in:
parent
3bbf5d03e2
commit
f95a277ac5
1
.github/actions/spelling/expect.txt
vendored
1
.github/actions/spelling/expect.txt
vendored
@ -1221,6 +1221,7 @@ PGL
|
|||||||
pglist
|
pglist
|
||||||
pgno
|
pgno
|
||||||
pgnumber
|
pgnumber
|
||||||
|
pgop
|
||||||
pgr
|
pgr
|
||||||
pgsize
|
pgsize
|
||||||
pgstate
|
pgstate
|
||||||
|
17
mdbx.h
17
mdbx.h
@ -2239,6 +2239,23 @@ struct MDBX_envinfo {
|
|||||||
/** Current environment mode.
|
/** Current environment mode.
|
||||||
* The same as \ref mdbx_env_get_flags() returns. */
|
* The same as \ref mdbx_env_get_flags() returns. */
|
||||||
uint32_t mi_mode;
|
uint32_t mi_mode;
|
||||||
|
|
||||||
|
/** Statistics of page operations.
|
||||||
|
* \details Overall statistics of page operations of all (running, completed
|
||||||
|
* and aborted) transactions in the current multi-process session (since the
|
||||||
|
* first process opened the database). */
|
||||||
|
struct {
|
||||||
|
uint64_t newly; /**< Quantity of a new pages added */
|
||||||
|
uint64_t cow; /**< Quantity of pages copied for update */
|
||||||
|
uint64_t clone; /**< Quantity of parent's dirty pages clones
|
||||||
|
for nested transactions */
|
||||||
|
uint64_t split; /**< Page splits */
|
||||||
|
uint64_t merge; /**< Page merges */
|
||||||
|
uint64_t spill; /**< Quantity of spilled dirty pages */
|
||||||
|
uint64_t unspill; /**< Quantity of unspilled/reloaded pages */
|
||||||
|
uint64_t wops; /**< Number of explicit write operations (not a pages)
|
||||||
|
to a disk */
|
||||||
|
} mi_pgop_stat;
|
||||||
};
|
};
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
/** \ingroup c_statinfo */
|
/** \ingroup c_statinfo */
|
||||||
|
101
src/core.c
101
src/core.c
@ -1040,15 +1040,29 @@ static __always_inline uint64_t safe64_read(const MDBX_atomic_uint64_t *p) {
|
|||||||
return atomic_load32(&p->high, mo_AcquireRelease) != UINT32_MAX;
|
return atomic_load32(&p->high, mo_AcquireRelease) != UINT32_MAX;
|
||||||
#endif /* MDBX_64BIT_ATOMIC */
|
#endif /* MDBX_64BIT_ATOMIC */
|
||||||
}
|
}
|
||||||
|
#endif /* unused for now */
|
||||||
|
|
||||||
|
/* non-atomic write with safety for reading a half-updated value */
|
||||||
static __always_inline void safe64_update(MDBX_atomic_uint64_t *p,
|
static __always_inline void safe64_update(MDBX_atomic_uint64_t *p,
|
||||||
const uint64_t v) {
|
const uint64_t v) {
|
||||||
#if MDBX_64BIT_ATOMIC
|
#if MDBX_64BIT_ATOMIC
|
||||||
|
atomic_store64(p, v, mo_Relaxed);
|
||||||
|
#else
|
||||||
safe64_reset(p, true);
|
safe64_reset(p, true);
|
||||||
#endif /* MDBX_64BIT_ATOMIC */
|
|
||||||
safe64_write(p, v);
|
safe64_write(p, v);
|
||||||
|
#endif /* MDBX_64BIT_ATOMIC */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non-atomic increment with safety for reading a half-updated value */
|
||||||
|
static
|
||||||
|
#if MDBX_64BIT_ATOMIC
|
||||||
|
__always_inline
|
||||||
|
#endif /* MDBX_64BIT_ATOMIC */
|
||||||
|
void
|
||||||
|
safe64_inc(MDBX_atomic_uint64_t *p, const uint64_t v) {
|
||||||
|
assert(v > 0);
|
||||||
|
safe64_update(p, atomic_load64(p, mo_Relaxed) + v);
|
||||||
}
|
}
|
||||||
#endif /* unused for now */
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* rthc (tls keys and destructors) */
|
/* rthc (tls keys and destructors) */
|
||||||
@ -3530,7 +3544,7 @@ static txnid_t mdbx_kick_longlived_readers(MDBX_env *env,
|
|||||||
const txnid_t laggard);
|
const txnid_t laggard);
|
||||||
|
|
||||||
static struct page_result mdbx_page_new(MDBX_cursor *mc, const unsigned flags,
|
static struct page_result mdbx_page_new(MDBX_cursor *mc, const unsigned flags,
|
||||||
const unsigned num);
|
const unsigned npages);
|
||||||
static int mdbx_page_touch(MDBX_cursor *mc);
|
static int mdbx_page_touch(MDBX_cursor *mc);
|
||||||
static int mdbx_cursor_touch(MDBX_cursor *mc);
|
static int mdbx_cursor_touch(MDBX_cursor *mc);
|
||||||
static int mdbx_touch_dbi(MDBX_cursor *mc);
|
static int mdbx_touch_dbi(MDBX_cursor *mc);
|
||||||
@ -4984,6 +4998,10 @@ static int mdbx_iov_write(MDBX_txn *const txn, struct mdbx_iov_ctx *ctx) {
|
|||||||
for (unsigned i = 0; i < ctx->iov_items; i++)
|
for (unsigned i = 0; i < ctx->iov_items; i++)
|
||||||
mdbx_dpage_free(env, (MDBX_page *)ctx->iov[i].iov_base,
|
mdbx_dpage_free(env, (MDBX_page *)ctx->iov[i].iov_base,
|
||||||
bytes2pgno(env, ctx->iov[i].iov_len));
|
bytes2pgno(env, ctx->iov[i].iov_len));
|
||||||
|
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&txn->mt_env->me_pgop_stat->wops, ctx->iov_items);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
ctx->iov_items = 0;
|
ctx->iov_items = 0;
|
||||||
ctx->iov_bytes = 0;
|
ctx->iov_bytes = 0;
|
||||||
return rc;
|
return rc;
|
||||||
@ -5043,8 +5061,13 @@ static int spill_page(MDBX_txn *txn, struct mdbx_iov_ctx *ctx, MDBX_page *dp,
|
|||||||
mdbx_tassert(txn, !(txn->mt_flags & MDBX_WRITEMAP));
|
mdbx_tassert(txn, !(txn->mt_flags & MDBX_WRITEMAP));
|
||||||
pgno_t pgno = dp->mp_pgno;
|
pgno_t pgno = dp->mp_pgno;
|
||||||
int err = iov_page(txn, ctx, dp, npages);
|
int err = iov_page(txn, ctx, dp, npages);
|
||||||
if (likely(err == MDBX_SUCCESS))
|
if (likely(err == MDBX_SUCCESS)) {
|
||||||
err = mdbx_pnl_append_range(true, &txn->tw.spill_pages, pgno << 1, npages);
|
err = mdbx_pnl_append_range(true, &txn->tw.spill_pages, pgno << 1, npages);
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
if (likely(err == MDBX_SUCCESS))
|
||||||
|
safe64_inc(&txn->mt_env->me_pgop_stat->spill, npages);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6643,6 +6666,9 @@ mdbx_page_unspill(MDBX_txn *const txn, MDBX_page *mp) {
|
|||||||
ret.err = mdbx_page_dirty(txn, ret.page, npages);
|
ret.err = mdbx_page_dirty(txn, ret.page, npages);
|
||||||
if (unlikely(ret.err != MDBX_SUCCESS))
|
if (unlikely(ret.err != MDBX_SUCCESS))
|
||||||
return ret;
|
return ret;
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&txn->mt_env->me_pgop_stat->unspill, npages);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
ret.page->mp_flags |= (scan == txn) ? 0 : P_SPILLED;
|
ret.page->mp_flags |= (scan == txn) ? 0 : P_SPILLED;
|
||||||
ret.err = MDBX_SUCCESS;
|
ret.err = MDBX_SUCCESS;
|
||||||
return ret;
|
return ret;
|
||||||
@ -6707,6 +6733,9 @@ __hot static int mdbx_page_touch(MDBX_cursor *mc) {
|
|||||||
mc->mc_db->md_root = pgno;
|
mc->mc_db->md_root = pgno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&txn->mt_env->me_pgop_stat->cow, 1);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
mdbx_page_copy(np, mp, txn->mt_env->me_psize);
|
mdbx_page_copy(np, mp, txn->mt_env->me_psize);
|
||||||
np->mp_pgno = pgno;
|
np->mp_pgno = pgno;
|
||||||
np->mp_txnid = txn->mt_front;
|
np->mp_txnid = txn->mt_front;
|
||||||
@ -6740,6 +6769,10 @@ __hot static int mdbx_page_touch(MDBX_cursor *mc) {
|
|||||||
rc = mdbx_page_dirty(txn, np, 1);
|
rc = mdbx_page_dirty(txn, np, 1);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&txn->mt_env->me_pgop_stat->clone, 1);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -11670,6 +11703,9 @@ static __cold int mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
|
|||||||
#if MDBX_LOCKING > 0
|
#if MDBX_LOCKING > 0
|
||||||
env->me_wlock = &env->me_lckless_stub.wlock;
|
env->me_wlock = &env->me_lckless_stub.wlock;
|
||||||
#endif /* MDBX_LOCKING > 0 */
|
#endif /* MDBX_LOCKING > 0 */
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
env->me_pgop_stat = &env->me_lckless_stub.pgop_stat;
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
mdbx_debug("lck-setup:%s%s%s", " lck-less",
|
mdbx_debug("lck-setup:%s%s%s", " lck-less",
|
||||||
(env->me_flags & MDBX_RDONLY) ? " readonly" : "",
|
(env->me_flags & MDBX_RDONLY) ? " readonly" : "",
|
||||||
(rc == MDBX_RESULT_TRUE) ? " exclusive" : " cooperative");
|
(rc == MDBX_RESULT_TRUE) ? " exclusive" : " cooperative");
|
||||||
@ -11827,6 +11863,9 @@ static __cold int mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
|
|||||||
#if MDBX_LOCKING > 0
|
#if MDBX_LOCKING > 0
|
||||||
env->me_wlock = &lck->mti_wlock;
|
env->me_wlock = &lck->mti_wlock;
|
||||||
#endif /* MDBX_LOCKING > 0 */
|
#endif /* MDBX_LOCKING > 0 */
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
env->me_pgop_stat = &lck->mti_pgop_stat;
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
return lck_seize_rc;
|
return lck_seize_rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12418,6 +12457,9 @@ static __cold int mdbx_env_close0(MDBX_env *env) {
|
|||||||
env->me_discarded_tail = nullptr;
|
env->me_discarded_tail = nullptr;
|
||||||
env->me_readahead_anchor = nullptr;
|
env->me_readahead_anchor = nullptr;
|
||||||
env->me_meta_sync_txnid = nullptr;
|
env->me_meta_sync_txnid = nullptr;
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
env->me_pgop_stat = nullptr;
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
if (env->me_flags & MDBX_ENV_TXKEY)
|
if (env->me_flags & MDBX_ENV_TXKEY)
|
||||||
mdbx_rthc_remove(env->me_txkey);
|
mdbx_rthc_remove(env->me_txkey);
|
||||||
|
|
||||||
@ -14546,6 +14588,9 @@ int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&mc->mc_txn->mt_env->me_pgop_stat->clone, ovpages);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
memcpy(np, pgr.page, PAGEHDRSZ); /* Copy header of page */
|
memcpy(np, pgr.page, PAGEHDRSZ); /* Copy header of page */
|
||||||
pgr.page = np;
|
pgr.page = np;
|
||||||
mdbx_cassert(mc, mdbx_dirtylist_check(mc->mc_txn));
|
mdbx_cassert(mc, mdbx_dirtylist_check(mc->mc_txn));
|
||||||
@ -15047,17 +15092,20 @@ fail:
|
|||||||
*
|
*
|
||||||
* Returns 0 on success, non-zero on failure. */
|
* Returns 0 on success, non-zero on failure. */
|
||||||
static struct page_result mdbx_page_new(MDBX_cursor *mc, const unsigned flags,
|
static struct page_result mdbx_page_new(MDBX_cursor *mc, const unsigned flags,
|
||||||
const unsigned num) {
|
const unsigned npages) {
|
||||||
struct page_result ret = mdbx_page_alloc(mc, num, MDBX_ALLOC_ALL);
|
struct page_result ret = mdbx_page_alloc(mc, npages, MDBX_ALLOC_ALL);
|
||||||
if (unlikely(ret.err != MDBX_SUCCESS))
|
if (unlikely(ret.err != MDBX_SUCCESS))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
mdbx_debug("db %u allocated new page %" PRIaPGNO ", num %u", mc->mc_dbi,
|
mdbx_debug("db %u allocated new page %" PRIaPGNO ", num %u", mc->mc_dbi,
|
||||||
ret.page->mp_pgno, num);
|
ret.page->mp_pgno, npages);
|
||||||
ret.page->mp_flags = (uint16_t)flags;
|
ret.page->mp_flags = (uint16_t)flags;
|
||||||
ret.page->mp_txnid = mc->mc_txn->mt_front;
|
ret.page->mp_txnid = mc->mc_txn->mt_front;
|
||||||
mdbx_cassert(mc, *mc->mc_dbistate & DBI_DIRTY);
|
mdbx_cassert(mc, *mc->mc_dbistate & DBI_DIRTY);
|
||||||
mdbx_cassert(mc, mc->mc_txn->mt_flags & MDBX_TXN_DIRTY);
|
mdbx_cassert(mc, mc->mc_txn->mt_flags & MDBX_TXN_DIRTY);
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&mc->mc_txn->mt_env->me_pgop_stat->newly, npages);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
|
|
||||||
if (likely((flags & P_OVERFLOW) == 0)) {
|
if (likely((flags & P_OVERFLOW) == 0)) {
|
||||||
STATIC_ASSERT(P_BRANCH == 1);
|
STATIC_ASSERT(P_BRANCH == 1);
|
||||||
@ -15072,8 +15120,8 @@ static struct page_result mdbx_page_new(MDBX_cursor *mc, const unsigned flags,
|
|||||||
outer->md_leaf_pages += 1 - is_branch;
|
outer->md_leaf_pages += 1 - is_branch;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mc->mc_db->md_overflow_pages += num;
|
mc->mc_db->md_overflow_pages += npages;
|
||||||
ret.page->mp_pages = num;
|
ret.page->mp_pages = npages;
|
||||||
mdbx_cassert(mc, !(mc->mc_flags & C_SUB));
|
mdbx_cassert(mc, !(mc->mc_flags & C_SUB));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16394,6 +16442,10 @@ static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) {
|
|||||||
mdbx_cassert(cdst, cdst->mc_snum <= cdst->mc_db->md_depth);
|
mdbx_cassert(cdst, cdst->mc_snum <= cdst->mc_db->md_depth);
|
||||||
mdbx_cassert(cdst, cdst->mc_snum == cdst->mc_top + 1);
|
mdbx_cassert(cdst, cdst->mc_snum == cdst->mc_top + 1);
|
||||||
|
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&cdst->mc_txn->mt_env->me_pgop_stat->merge, 1);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
|
|
||||||
if (IS_LEAF(cdst->mc_pg[cdst->mc_top])) {
|
if (IS_LEAF(cdst->mc_pg[cdst->mc_top])) {
|
||||||
/* LY: don't touch cursor if top-page is a LEAF */
|
/* LY: don't touch cursor if top-page is a LEAF */
|
||||||
mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) ||
|
mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) ||
|
||||||
@ -16403,7 +16455,7 @@ static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) {
|
|||||||
|
|
||||||
mdbx_cassert(cdst, page_numkeys(top_page) == dst_nkeys + src_nkeys);
|
mdbx_cassert(cdst, page_numkeys(top_page) == dst_nkeys + src_nkeys);
|
||||||
|
|
||||||
if (pagetype != PAGETYPE(top_page)) {
|
if (unlikely(pagetype != PAGETYPE(top_page))) {
|
||||||
/* LY: LEAF-page becomes BRANCH, unable restore cursor's stack */
|
/* LY: LEAF-page becomes BRANCH, unable restore cursor's stack */
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
@ -17873,6 +17925,9 @@ done:
|
|||||||
if (!(node_flags(node) & F_BIGDATA))
|
if (!(node_flags(node) & F_BIGDATA))
|
||||||
newdata->iov_base = node_data(node);
|
newdata->iov_base = node_data(node);
|
||||||
}
|
}
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
safe64_inc(&env->me_pgop_stat->split, 1);
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
}
|
}
|
||||||
|
|
||||||
mdbx_debug("<< mp #%u, rc %d", mp->mp_pgno, rc);
|
mdbx_debug("<< mp #%u, rc %d", mp->mp_pgno, rc);
|
||||||
@ -18849,7 +18904,9 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid);
|
const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid);
|
||||||
if (unlikely(bytes != sizeof(MDBX_envinfo)) && bytes != size_before_bootid)
|
const size_t size_before_pgop_stat = offsetof(MDBX_envinfo, mi_pgop_stat);
|
||||||
|
if (unlikely(bytes != sizeof(MDBX_envinfo)) && bytes != size_before_bootid &&
|
||||||
|
bytes != size_before_pgop_stat)
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
/* is the environment open? (https://github.com/erthink/libmdbx/issues/171) */
|
/* is the environment open? (https://github.com/erthink/libmdbx/issues/171) */
|
||||||
@ -18964,6 +19021,28 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn,
|
|||||||
arg->mi_mode = lck ? lck->mti_envmode.weak : env->me_flags;
|
arg->mi_mode = lck ? lck->mti_envmode.weak : env->me_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (likely(bytes > size_before_pgop_stat)) {
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
arg->mi_pgop_stat.newly =
|
||||||
|
atomic_load64(&env->me_pgop_stat->newly, mo_Relaxed);
|
||||||
|
arg->mi_pgop_stat.cow = atomic_load64(&env->me_pgop_stat->cow, mo_Relaxed);
|
||||||
|
arg->mi_pgop_stat.clone =
|
||||||
|
atomic_load64(&env->me_pgop_stat->clone, mo_Relaxed);
|
||||||
|
arg->mi_pgop_stat.split =
|
||||||
|
atomic_load64(&env->me_pgop_stat->split, mo_Relaxed);
|
||||||
|
arg->mi_pgop_stat.merge =
|
||||||
|
atomic_load64(&env->me_pgop_stat->merge, mo_Relaxed);
|
||||||
|
arg->mi_pgop_stat.spill =
|
||||||
|
atomic_load64(&env->me_pgop_stat->spill, mo_Relaxed);
|
||||||
|
arg->mi_pgop_stat.unspill =
|
||||||
|
atomic_load64(&env->me_pgop_stat->unspill, mo_Relaxed);
|
||||||
|
arg->mi_pgop_stat.wops =
|
||||||
|
atomic_load64(&env->me_pgop_stat->wops, mo_Relaxed);
|
||||||
|
#else
|
||||||
|
memset(&arg->mi_pgop_stat, 0, sizeof(arg->mi_pgop_stat));
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT*/
|
||||||
|
}
|
||||||
|
|
||||||
arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid = 0;
|
arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid = 0;
|
||||||
if (lck) {
|
if (lck) {
|
||||||
arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid =
|
arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid =
|
||||||
|
@ -331,8 +331,13 @@ atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value,
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused __always_inline uint64_t
|
static __maybe_unused
|
||||||
atomic_load64(const MDBX_atomic_uint64_t *p, enum MDBX_memory_order order) {
|
#if MDBX_64BIT_ATOMIC
|
||||||
|
__always_inline
|
||||||
|
#endif /* MDBX_64BIT_ATOMIC */
|
||||||
|
uint64_t
|
||||||
|
atomic_load64(const MDBX_atomic_uint64_t *p,
|
||||||
|
enum MDBX_memory_order order) {
|
||||||
STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8);
|
STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8);
|
||||||
#if MDBX_64BIT_ATOMIC
|
#if MDBX_64BIT_ATOMIC
|
||||||
#ifdef MDBX_HAVE_C11ATOMICS
|
#ifdef MDBX_HAVE_C11ATOMICS
|
||||||
@ -376,10 +381,10 @@ atomic_load64(const MDBX_atomic_uint64_t *p, enum MDBX_memory_order order) {
|
|||||||
* recognizable, and it will reflect any byte order mismatches. */
|
* recognizable, and it will reflect any byte order mismatches. */
|
||||||
#define MDBX_MAGIC UINT64_C(/* 56-bit prime */ 0x59659DBDEF4C11)
|
#define MDBX_MAGIC UINT64_C(/* 56-bit prime */ 0x59659DBDEF4C11)
|
||||||
|
|
||||||
/* The version number for a database's datafile format. */
|
/* FROZEN: The version number for a database's datafile format. */
|
||||||
#define MDBX_DATA_VERSION 2
|
#define MDBX_DATA_VERSION 2
|
||||||
/* The version number for a database's lockfile format. */
|
/* The version number for a database's lockfile format. */
|
||||||
#define MDBX_LOCK_VERSION 3
|
#define MDBX_LOCK_VERSION 4
|
||||||
|
|
||||||
/* handle for the DB used to track free pages. */
|
/* handle for the DB used to track free pages. */
|
||||||
#define FREE_DBI 0
|
#define FREE_DBI 0
|
||||||
@ -571,6 +576,23 @@ typedef struct MDBX_page {
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
/* Statistics of page operations overall of all (running, completed and aborted)
|
||||||
|
* transactions */
|
||||||
|
typedef struct {
|
||||||
|
MDBX_atomic_uint64_t newly; /* Quantity of a new pages added */
|
||||||
|
MDBX_atomic_uint64_t cow; /* Quantity of pages copied for update */
|
||||||
|
MDBX_atomic_uint64_t clone; /* Quantity of parent's dirty pages clones
|
||||||
|
for nested transactions */
|
||||||
|
MDBX_atomic_uint64_t split; /* Page splits */
|
||||||
|
MDBX_atomic_uint64_t merge; /* Page merges */
|
||||||
|
MDBX_atomic_uint64_t spill; /* Quantity of spilled dirty pages */
|
||||||
|
MDBX_atomic_uint64_t unspill; /* Quantity of unspilled/reloaded pages */
|
||||||
|
MDBX_atomic_uint64_t
|
||||||
|
wops; /* Number of explicit write operations (not a pages) to a disk */
|
||||||
|
} MDBX_pgop_stat_t;
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
|
|
||||||
#if MDBX_LOCKING == MDBX_LOCKING_WIN32FILES
|
#if MDBX_LOCKING == MDBX_LOCKING_WIN32FILES
|
||||||
#define MDBX_CLOCK_SIGN UINT32_C(0xF10C)
|
#define MDBX_CLOCK_SIGN UINT32_C(0xF10C)
|
||||||
typedef void mdbx_ipclock_t;
|
typedef void mdbx_ipclock_t;
|
||||||
@ -702,6 +724,14 @@ typedef struct MDBX_lockinfo {
|
|||||||
|
|
||||||
alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/
|
alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/
|
||||||
|
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
/* Statistics of costly ops of all (running, completed and aborted)
|
||||||
|
* transactions */
|
||||||
|
MDBX_pgop_stat_t mti_pgop_stat;
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT*/
|
||||||
|
|
||||||
|
alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/
|
||||||
|
|
||||||
/* Write transaction lock. */
|
/* Write transaction lock. */
|
||||||
#if MDBX_LOCKING > 0
|
#if MDBX_LOCKING > 0
|
||||||
mdbx_ipclock_t mti_wlock;
|
mdbx_ipclock_t mti_wlock;
|
||||||
@ -1134,6 +1164,9 @@ struct MDBX_env {
|
|||||||
atomic_pgno_t *me_discarded_tail;
|
atomic_pgno_t *me_discarded_tail;
|
||||||
pgno_t *me_readahead_anchor;
|
pgno_t *me_readahead_anchor;
|
||||||
MDBX_atomic_uint32_t *me_meta_sync_txnid;
|
MDBX_atomic_uint32_t *me_meta_sync_txnid;
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
MDBX_pgop_stat_t *me_pgop_stat;
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT*/
|
||||||
MDBX_hsr_func *me_hsr_callback; /* Callback for kicking laggard readers */
|
MDBX_hsr_func *me_hsr_callback; /* Callback for kicking laggard readers */
|
||||||
struct {
|
struct {
|
||||||
unsigned dp_reserve_limit;
|
unsigned dp_reserve_limit;
|
||||||
@ -1202,6 +1235,9 @@ struct MDBX_env {
|
|||||||
atomic_pgno_t discarded_tail;
|
atomic_pgno_t discarded_tail;
|
||||||
pgno_t readahead_anchor;
|
pgno_t readahead_anchor;
|
||||||
MDBX_atomic_uint32_t meta_sync_txnid;
|
MDBX_atomic_uint32_t meta_sync_txnid;
|
||||||
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
|
MDBX_pgop_stat_t pgop_stat;
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT*/
|
||||||
} me_lckless_stub;
|
} me_lckless_stub;
|
||||||
|
|
||||||
/* -------------------------------------------------------------- debugging */
|
/* -------------------------------------------------------------- debugging */
|
||||||
|
@ -98,6 +98,14 @@
|
|||||||
#error MDBX_ENABLE_REFUND must be defined as 0 or 1
|
#error MDBX_ENABLE_REFUND must be defined as 0 or 1
|
||||||
#endif /* MDBX_ENABLE_REFUND */
|
#endif /* MDBX_ENABLE_REFUND */
|
||||||
|
|
||||||
|
/** Controls gathering statistics for page operations. */
|
||||||
|
#ifndef MDBX_ENABLE_PGOP_STAT
|
||||||
|
#define MDBX_ENABLE_PGOP_STAT 1
|
||||||
|
#endif
|
||||||
|
#if !(MDBX_ENABLE_PGOP_STAT == 0 || MDBX_ENABLE_PGOP_STAT == 1)
|
||||||
|
#error MDBX_ENABLE_PGOP_STAT must be defined as 0 or 1
|
||||||
|
#endif /* MDBX_ENABLE_PGOP_STAT */
|
||||||
|
|
||||||
/** Controls use of POSIX madvise() hints and friends. */
|
/** Controls use of POSIX madvise() hints and friends. */
|
||||||
#ifndef MDBX_ENABLE_MADVISE
|
#ifndef MDBX_ENABLE_MADVISE
|
||||||
#define MDBX_ENABLE_MADVISE 1
|
#define MDBX_ENABLE_MADVISE 1
|
||||||
|
Loading…
Reference in New Issue
Block a user