mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-30 11:29:19 +08:00
mdbx: fix performance degradation in the absence of readers.
Change-Id: I59a51b61918463e68d3e0490c715f4dcc9ecb788
This commit is contained in:
parent
f9b1bbe1e3
commit
b6f14780e3
@ -405,7 +405,7 @@ typedef struct MDBX_lockinfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
volatile uint32_t mti_reader_finished_flag;
|
volatile uint32_t mti_readers_refresh_flag;
|
||||||
uint64_t align_reader_finished_flag;
|
uint64_t align_reader_finished_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
68
src/mdbx.c
68
src/mdbx.c
@ -1556,26 +1556,51 @@ static txnid_t mdbx_find_oldest(MDBX_txn *txn) {
|
|||||||
const MDBX_env *env = txn->mt_env;
|
const MDBX_env *env = txn->mt_env;
|
||||||
MDBX_lockinfo *const lck = env->me_lck;
|
MDBX_lockinfo *const lck = env->me_lck;
|
||||||
|
|
||||||
txnid_t oldest = mdbx_reclaiming_detent(env);
|
const txnid_t edge = mdbx_reclaiming_detent(env);
|
||||||
mdbx_tassert(txn, oldest <= txn->mt_txnid - 1);
|
mdbx_tassert(txn, edge <= txn->mt_txnid - 1);
|
||||||
const txnid_t last_oldest = lck->mti_oldest;
|
const txnid_t last_oldest = lck->mti_oldest;
|
||||||
mdbx_tassert(txn, oldest >= last_oldest);
|
mdbx_tassert(txn, edge >= last_oldest);
|
||||||
if (last_oldest == oldest ||
|
if (last_oldest == edge)
|
||||||
lck->mti_reader_finished_flag == MDBX_STRING_TETRAD("None"))
|
return edge;
|
||||||
return last_oldest;
|
|
||||||
|
|
||||||
const unsigned snap_nreaders = lck->mti_numreaders;
|
const uint32_t nothing_changed = MDBX_STRING_TETRAD("None");
|
||||||
lck->mti_reader_finished_flag = MDBX_STRING_TETRAD("None");
|
const uint32_t no_readers = MDBX_STRING_TETRAD("Void");
|
||||||
for (unsigned i = 0; i < snap_nreaders; ++i) {
|
const uint32_t snap_readers_refresh_flag = lck->mti_readers_refresh_flag;
|
||||||
if (lck->mti_readers[i].mr_pid) {
|
mdbx_jitter4testing(false);
|
||||||
/* mdbx_jitter4testing(true); */
|
if (snap_readers_refresh_flag == nothing_changed)
|
||||||
const txnid_t snap = lck->mti_readers[i].mr_txnid;
|
return last_oldest;
|
||||||
if (oldest > snap && last_oldest <= /* ignore pending updates */ snap) {
|
if (snap_readers_refresh_flag == no_readers) {
|
||||||
oldest = snap;
|
mdbx_notice("no-reareds, update oldest %" PRIaTXN " -> %" PRIaTXN,
|
||||||
if (oldest == last_oldest)
|
last_oldest, edge);
|
||||||
break;
|
mdbx_tassert(txn, edge >= lck->mti_oldest);
|
||||||
|
return lck->mti_oldest = edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned pending = 0;
|
||||||
|
txnid_t oldest = edge;
|
||||||
|
while (true) {
|
||||||
|
lck->mti_readers_refresh_flag = nothing_changed;
|
||||||
|
mdbx_coherent_barrier();
|
||||||
|
const unsigned snap_nreaders = lck->mti_numreaders;
|
||||||
|
for (unsigned i = 0; i < snap_nreaders; ++i) {
|
||||||
|
if (lck->mti_readers[i].mr_pid) {
|
||||||
|
/* mdbx_jitter4testing(true); */
|
||||||
|
const txnid_t snap = lck->mti_readers[i].mr_txnid;
|
||||||
|
pending += (snap < ~(txnid_t)0);
|
||||||
|
if (oldest > snap && last_oldest <= /* ignore pending updates */ snap) {
|
||||||
|
oldest = snap;
|
||||||
|
if (oldest == last_oldest)
|
||||||
|
return oldest;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(lck->mti_readers_refresh_flag != nothing_changed))
|
||||||
|
continue;
|
||||||
|
if (pending > 0 ||
|
||||||
|
mdbx_atomic_compare_and_swap32(&lck->mti_readers_refresh_flag,
|
||||||
|
nothing_changed, no_readers))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldest != last_oldest) {
|
if (oldest != last_oldest) {
|
||||||
@ -2529,6 +2554,7 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
|||||||
mdbx_assert(env, r->mr_tid == mdbx_thread_self());
|
mdbx_assert(env, r->mr_tid == mdbx_thread_self());
|
||||||
mdbx_assert(env, r->mr_txnid == snap);
|
mdbx_assert(env, r->mr_txnid == snap);
|
||||||
mdbx_coherent_barrier();
|
mdbx_coherent_barrier();
|
||||||
|
env->me_lck->mti_readers_refresh_flag = true;
|
||||||
}
|
}
|
||||||
mdbx_jitter4testing(true);
|
mdbx_jitter4testing(true);
|
||||||
|
|
||||||
@ -2544,12 +2570,10 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
|||||||
mdbx_compiler_barrier();
|
mdbx_compiler_barrier();
|
||||||
if (likely(meta == mdbx_meta_head(env) &&
|
if (likely(meta == mdbx_meta_head(env) &&
|
||||||
snap == mdbx_meta_txnid_fluid(env, meta) &&
|
snap == mdbx_meta_txnid_fluid(env, meta) &&
|
||||||
snap >= env->me_oldest[0])) {
|
snap >= *env->me_oldest)) {
|
||||||
mdbx_jitter4testing(false);
|
mdbx_jitter4testing(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (env->me_lck)
|
|
||||||
env->me_lck->mti_reader_finished_flag = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(txn->mt_txnid == 0)) {
|
if (unlikely(txn->mt_txnid == 0)) {
|
||||||
@ -2854,7 +2878,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
|
|||||||
if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)) {
|
if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)) {
|
||||||
if (txn->mt_ro_reader) {
|
if (txn->mt_ro_reader) {
|
||||||
txn->mt_ro_reader->mr_txnid = ~(txnid_t)0;
|
txn->mt_ro_reader->mr_txnid = ~(txnid_t)0;
|
||||||
env->me_lck->mti_reader_finished_flag = true;
|
env->me_lck->mti_readers_refresh_flag = true;
|
||||||
if (mode & MDBX_END_SLOT) {
|
if (mode & MDBX_END_SLOT) {
|
||||||
if ((env->me_flags & MDBX_ENV_TXKEY) == 0)
|
if ((env->me_flags & MDBX_ENV_TXKEY) == 0)
|
||||||
txn->mt_ro_reader->mr_pid = 0;
|
txn->mt_ro_reader->mr_pid = 0;
|
||||||
@ -10645,7 +10669,7 @@ int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) {
|
|||||||
mdbx_debug("clear stale reader pid %" PRIuPTR " txn %" PRIaTXN "",
|
mdbx_debug("clear stale reader pid %" PRIuPTR " txn %" PRIaTXN "",
|
||||||
(size_t)pid, lck->mti_readers[j].mr_txnid);
|
(size_t)pid, lck->mti_readers[j].mr_txnid);
|
||||||
lck->mti_readers[j].mr_pid = 0;
|
lck->mti_readers[j].mr_pid = 0;
|
||||||
lck->mti_reader_finished_flag = true;
|
lck->mti_readers_refresh_flag = true;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10754,7 +10778,7 @@ static txnid_t __cold mdbx_oomkick(MDBX_env *env, const txnid_t laggard) {
|
|||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
asleep->mr_txnid = ~(txnid_t)0;
|
asleep->mr_txnid = ~(txnid_t)0;
|
||||||
env->me_lck->mti_reader_finished_flag = true;
|
env->me_lck->mti_readers_refresh_flag = true;
|
||||||
if (rc > 1) {
|
if (rc > 1) {
|
||||||
asleep->mr_tid = 0;
|
asleep->mr_tid = 0;
|
||||||
asleep->mr_pid = 0;
|
asleep->mr_pid = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user