mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-21 17:38:20 +08:00
mdbx: refine update_gc() for large-transaction cases.
This commit is contained in:
parent
c250500afd
commit
7ef61e12c0
@ -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--;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user