mdbx: refine update_gc() for large-transaction cases.

This commit is contained in:
Leonid Yuriev 2019-11-16 00:18:20 +03:00
parent c250500afd
commit 7ef61e12c0

View File

@ -5752,7 +5752,6 @@ retry:
goto bailout; goto bailout;
} while (cleaned_gc_slot < MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)); } while (cleaned_gc_slot < MDBX_PNL_SIZE(txn->tw.lifo_reclaimed));
mdbx_txl_sort(txn->tw.lifo_reclaimed); mdbx_txl_sort(txn->tw.lifo_reclaimed);
gc_rid = MDBX_PNL_LAST(txn->tw.lifo_reclaimed);
} }
} else { } else {
/* If using records from GC which we have not yet deleted, /* If using records from GC which we have not yet deleted,
@ -5951,43 +5950,61 @@ retry:
const unsigned prefer_max_scatter = 257; const unsigned prefer_max_scatter = 257;
txnid_t reservation_gc_id; txnid_t reservation_gc_id;
if (lifo) { if (lifo) {
const unsigned lifo_len = if (txn->tw.lifo_reclaimed == nullptr) {
txn->tw.lifo_reclaimed txn->tw.lifo_reclaimed = mdbx_txl_alloc();
? (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) if (unlikely(!txn->tw.lifo_reclaimed)) {
: 0; rc = MDBX_ENOMEM;
if (lifo_len < prefer_max_scatter && goto bailout;
left > (lifo_len - reused_gc_slot) * env->me_maxgc_ov1page) { }
}
if ((unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) <
prefer_max_scatter &&
left > ((unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) -
reused_gc_slot) *
env->me_maxgc_ov1page) {
/* LY: need just a txn-id for save page list. */ /* LY: need just a txn-id for save page list. */
mc.mc_flags &= ~C_RECLAIMING; mc.mc_flags &= ~C_RECLAIMING;
rc = mdbx_page_alloc(&mc, 0, NULL, MDBX_ALLOC_GC | MDBX_ALLOC_KICK); bool need_cleanup = false;
do {
rc = mdbx_page_alloc(&mc, 0, NULL, MDBX_ALLOC_GC | MDBX_ALLOC_KICK);
if (likely(rc == MDBX_SUCCESS)) {
mdbx_trace("%s: took @%" PRIaTXN " from GC", dbg_prefix_mode,
MDBX_PNL_LAST(txn->tw.lifo_reclaimed));
need_cleanup = true;
}
} while (rc == MDBX_SUCCESS &&
(unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) <
prefer_max_scatter &&
left > ((unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) -
reused_gc_slot) *
env->me_maxgc_ov1page);
mc.mc_flags |= C_RECLAIMING; mc.mc_flags |= C_RECLAIMING;
if (likely(rc == MDBX_SUCCESS)) { if (likely(rc == MDBX_SUCCESS)) {
/* LY: ok, reclaimed from GC. */ mdbx_trace("%s: got enough from GC.", dbg_prefix_mode);
mdbx_trace("%s: took @%" PRIaTXN " from GC, continue",
dbg_prefix_mode, MDBX_PNL_LAST(txn->tw.lifo_reclaimed));
continue; continue;
} } else if (unlikely(rc != MDBX_NOTFOUND))
if (unlikely(rc != MDBX_NOTFOUND)) /* LY: some troubles... */
/* LY: other troubles... */
goto bailout; goto bailout;
/* LY: GC is empty, will look any free txn-id in high2low order. */ if (MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)) {
if (unlikely(gc_rid == 0)) { if (need_cleanup)
mdbx_txl_sort(txn->tw.lifo_reclaimed);
gc_rid = MDBX_PNL_LAST(txn->tw.lifo_reclaimed);
} else {
mdbx_tassert(txn, txn->tw.last_reclaimed == 0); mdbx_tassert(txn, txn->tw.last_reclaimed == 0);
txn->tw.last_reclaimed = gc_rid = mdbx_find_oldest(txn) - 1; txn->tw.last_reclaimed = gc_rid = mdbx_find_oldest(txn) - 1;
if (txn->tw.lifo_reclaimed == nullptr) { mdbx_trace("%s: none recycled yet, set rid to @%" PRIaTXN,
txn->tw.lifo_reclaimed = mdbx_txl_alloc(); dbg_prefix_mode, gc_rid);
if (unlikely(!txn->tw.lifo_reclaimed)) {
rc = MDBX_ENOMEM;
goto bailout;
}
}
} }
mdbx_tassert(txn, txn->tw.lifo_reclaimed != nullptr); /* LY: GC is empty, will look any free txn-id in high2low order. */
rc = MDBX_RESULT_TRUE; while (MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) < prefer_max_scatter &&
do { left > ((unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) -
if (unlikely(gc_rid <= 1)) { reused_gc_slot) *
env->me_maxgc_ov1page) {
if (unlikely(gc_rid < 2)) {
if (unlikely(MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) <= if (unlikely(MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) <=
reused_gc_slot)) { reused_gc_slot)) {
mdbx_notice("** restart: reserve depleted (reused_gc_slot %u >= " mdbx_notice("** restart: reserve depleted (reused_gc_slot %u >= "
@ -6003,22 +6020,24 @@ retry:
rc = mdbx_txl_append(&txn->tw.lifo_reclaimed, --gc_rid); rc = mdbx_txl_append(&txn->tw.lifo_reclaimed, --gc_rid);
if (unlikely(rc != MDBX_SUCCESS)) if (unlikely(rc != MDBX_SUCCESS))
goto bailout; goto bailout;
cleaned_gc_slot += 1 /* mark GC cleanup is not needed. */;
if (reused_gc_slot)
/* rare case, but it is better to clear and re-create GC entries
* with less fragmentation. */
need_cleanup = true;
else
cleaned_gc_slot +=
1 /* mark cleanup is not needed for added slot. */;
mdbx_trace("%s: append @%" PRIaTXN mdbx_trace("%s: append @%" PRIaTXN
" to lifo-reclaimed, cleaned-gc-slot = %u", " to lifo-reclaimed, cleaned-gc-slot = %u",
dbg_prefix_mode, gc_rid, cleaned_gc_slot); dbg_prefix_mode, gc_rid, cleaned_gc_slot);
} while (gc_rid && }
MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) < prefer_max_scatter &&
left > ((unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - if (need_cleanup) {
reused_gc_slot) *
env->me_maxgc_ov1page);
if (reused_gc_slot && rc != MDBX_RESULT_TRUE) {
mdbx_trace("%s: restart inner-loop since reused_gc_slot %u > 0",
dbg_prefix_mode, reused_gc_slot);
/* rare case, but it is better to clear and re-create GC entries with
* less fragmentation. */
cleaned_gc_slot = 0; cleaned_gc_slot = 0;
mdbx_trace("%s: restart inner-loop to clear and re-create GC entries",
dbg_prefix_mode);
continue; continue;
} }
} }
@ -6048,12 +6067,10 @@ retry:
gc_rid = gc_first - 1; gc_rid = gc_first - 1;
if (unlikely(gc_rid == 0)) { if (unlikely(gc_rid == 0)) {
mdbx_error("%s", "** no GC tail-space to store"); mdbx_error("%s", "** no GC tail-space to store");
rc = MDBX_PROBLEM; goto retry;
goto bailout;
} }
} else if (rc != MDBX_NOTFOUND) } else if (rc != MDBX_NOTFOUND)
goto bailout; goto bailout;
mdbx_tassert(txn, txn->tw.last_reclaimed == 0);
txn->tw.last_reclaimed = gc_rid; txn->tw.last_reclaimed = gc_rid;
} }
reservation_gc_id = gc_rid--; reservation_gc_id = gc_rid--;