mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-20 10:58:21 +08:00
mdbx: refine internal sort.
Change-Id: If07d9f6b7a7976e5e048eb1b8b7e0b65c4ed3fdd
This commit is contained in:
parent
d12b546a7d
commit
7d880a37dd
@ -1465,9 +1465,8 @@ static int lcklist_detach_locked(MDBX_env *env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* LY: State of the art quicksort-based sorting, with internal stack and
|
* LY: State of the art quicksort-based sorting, with internal stack
|
||||||
* shell-insertion-sort for small chunks (less than half of SORT_THRESHOLD).
|
* and bitonic-sort for small chunks. */
|
||||||
*/
|
|
||||||
|
|
||||||
#define SORT_CMP_SWAP(TYPE, CMP, a, b) \
|
#define SORT_CMP_SWAP(TYPE, CMP, a, b) \
|
||||||
do { \
|
do { \
|
||||||
@ -1942,24 +1941,10 @@ static int lcklist_detach_locked(MDBX_env *env) {
|
|||||||
SORT_CMP_SWAP(TYPE, CMP, begin[8], begin[9]); \
|
SORT_CMP_SWAP(TYPE, CMP, begin[8], begin[9]); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SORT_SHELLPASS(TYPE, CMP, begin, end, gap) \
|
#define SORT_INNER(TYPE, CMP, begin, end, len) \
|
||||||
for (TYPE *i = begin + gap; i < end; ++i) { \
|
|
||||||
for (TYPE *j = i - (gap); j >= begin && CMP(*i, *j); j -= gap) { \
|
|
||||||
const TYPE tmp = *i; \
|
|
||||||
do { \
|
|
||||||
j[gap] = *j; \
|
|
||||||
j -= gap; \
|
|
||||||
} while (j >= begin && CMP(tmp, *j)); \
|
|
||||||
j[gap] = tmp; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SORT_INTRA(TYPE, CMP, begin, end, len) \
|
|
||||||
switch (len) { \
|
switch (len) { \
|
||||||
default: \
|
default: \
|
||||||
SORT_SHELLPASS(TYPE, CMP, begin, end, 8); \
|
__unreachable(); \
|
||||||
SORT_SHELLPASS(TYPE, CMP, begin, end, 1); \
|
|
||||||
case 0: \
|
case 0: \
|
||||||
case 1: \
|
case 1: \
|
||||||
break; \
|
break; \
|
||||||
@ -2010,8 +1995,6 @@ static int lcklist_detach_locked(MDBX_env *env) {
|
|||||||
break; \
|
break; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SORT_THRESHOLD 16
|
|
||||||
|
|
||||||
#define SORT_SWAP(TYPE, a, b) \
|
#define SORT_SWAP(TYPE, a, b) \
|
||||||
do { \
|
do { \
|
||||||
const TYPE swap_tmp = (a); \
|
const TYPE swap_tmp = (a); \
|
||||||
@ -2033,7 +2016,14 @@ static int lcklist_detach_locked(MDBX_env *env) {
|
|||||||
high = top->hi; \
|
high = top->hi; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SORT_IMPL(NAME, TYPE, CMP) \
|
#define SORT_IMPL(NAME, EXPECT_LOW_CARDINALITY_OR_PRESORTED, TYPE, CMP) \
|
||||||
|
\
|
||||||
|
static __inline bool NAME##_is_sorted(const TYPE *first, const TYPE *last) { \
|
||||||
|
while (++first <= last) \
|
||||||
|
if (CMP(first[0], first[-1])) \
|
||||||
|
return false; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
typedef struct { \
|
typedef struct { \
|
||||||
TYPE *lo, *hi; \
|
TYPE *lo, *hi; \
|
||||||
@ -2046,9 +2036,9 @@ static int lcklist_detach_locked(MDBX_env *env) {
|
|||||||
TYPE *lo = begin; \
|
TYPE *lo = begin; \
|
||||||
while (true) { \
|
while (true) { \
|
||||||
const ptrdiff_t len = hi - lo; \
|
const ptrdiff_t len = hi - lo; \
|
||||||
if (len < SORT_THRESHOLD) { \
|
if (len < 16) { \
|
||||||
SORT_INTRA(TYPE, CMP, lo, hi + 1, len + 1); \
|
SORT_INNER(TYPE, CMP, lo, hi + 1, len + 1); \
|
||||||
if (top == stack) \
|
if (unlikely(top == stack)) \
|
||||||
break; \
|
break; \
|
||||||
SORT_POP(lo, hi); \
|
SORT_POP(lo, hi); \
|
||||||
continue; \
|
continue; \
|
||||||
@ -2061,22 +2051,25 @@ static int lcklist_detach_locked(MDBX_env *env) {
|
|||||||
\
|
\
|
||||||
TYPE *right = hi - 1; \
|
TYPE *right = hi - 1; \
|
||||||
TYPE *left = lo + 1; \
|
TYPE *left = lo + 1; \
|
||||||
do { \
|
while (1) { \
|
||||||
while (CMP(*mid, *right)) \
|
|
||||||
--right; \
|
|
||||||
while (CMP(*left, *mid)) \
|
while (CMP(*left, *mid)) \
|
||||||
++left; \
|
++left; \
|
||||||
if (left < right) { \
|
while (CMP(*mid, *right)) \
|
||||||
SORT_SWAP(TYPE, *left, *right); \
|
|
||||||
mid = (mid == left) ? right : (mid == right) ? left : mid; \
|
|
||||||
++left; \
|
|
||||||
--right; \
|
|
||||||
} else if (left == right) { \
|
|
||||||
++left; \
|
|
||||||
--right; \
|
--right; \
|
||||||
|
if (unlikely(left > right)) { \
|
||||||
|
if (EXPECT_LOW_CARDINALITY_OR_PRESORTED) { \
|
||||||
|
if (NAME##_is_sorted(lo, right)) \
|
||||||
|
lo = right + 1; \
|
||||||
|
if (NAME##_is_sorted(left, hi)) \
|
||||||
|
hi = left; \
|
||||||
|
} \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} while (left <= right); \
|
SORT_SWAP(TYPE, *left, *right); \
|
||||||
|
mid = (mid == left) ? right : (mid == right) ? left : mid; \
|
||||||
|
++left; \
|
||||||
|
--right; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
if (right - lo > hi - left) { \
|
if (right - lo > hi - left) { \
|
||||||
SORT_PUSH(lo, right); \
|
SORT_PUSH(lo, right); \
|
||||||
@ -2375,7 +2368,7 @@ static void __hot mdbx_pnl_xmerge(MDBX_PNL dst, const MDBX_PNL src) {
|
|||||||
assert(mdbx_pnl_check4assert(dst, MAX_PAGENO + 1));
|
assert(mdbx_pnl_check4assert(dst, MAX_PAGENO + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
SORT_IMPL(pgno_sort, pgno_t, MDBX_PNL_ORDERED)
|
SORT_IMPL(pgno_sort, false, pgno_t, MDBX_PNL_ORDERED)
|
||||||
static __hot void mdbx_pnl_sort(MDBX_PNL pnl) {
|
static __hot void mdbx_pnl_sort(MDBX_PNL pnl) {
|
||||||
pgno_sort(MDBX_PNL_BEGIN(pnl), MDBX_PNL_END(pnl));
|
pgno_sort(MDBX_PNL_BEGIN(pnl), MDBX_PNL_END(pnl));
|
||||||
assert(mdbx_pnl_check(pnl, MAX_PAGENO + 1));
|
assert(mdbx_pnl_check(pnl, MAX_PAGENO + 1));
|
||||||
@ -2485,7 +2478,7 @@ static __always_inline void mdbx_txl_xappend(MDBX_TXL tl, txnid_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define TXNID_SORT_CMP(first, last) ((first) > (last))
|
#define TXNID_SORT_CMP(first, last) ((first) > (last))
|
||||||
SORT_IMPL(txnid_sort, txnid_t, TXNID_SORT_CMP)
|
SORT_IMPL(txnid_sort, false, txnid_t, TXNID_SORT_CMP)
|
||||||
static void mdbx_txl_sort(MDBX_TXL tl) {
|
static void mdbx_txl_sort(MDBX_TXL tl) {
|
||||||
txnid_sort(MDBX_PNL_BEGIN(tl), MDBX_PNL_END(tl));
|
txnid_sort(MDBX_PNL_BEGIN(tl), MDBX_PNL_END(tl));
|
||||||
}
|
}
|
||||||
@ -2503,7 +2496,7 @@ static int __must_check_result mdbx_txl_append(MDBX_TXL *ptl, txnid_t id) {
|
|||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define DP_SORT_CMP(first, last) ((first).pgno < (last).pgno)
|
#define DP_SORT_CMP(first, last) ((first).pgno < (last).pgno)
|
||||||
SORT_IMPL(dp_sort, MDBX_DP, DP_SORT_CMP)
|
SORT_IMPL(dp_sort, false, MDBX_DP, DP_SORT_CMP)
|
||||||
static __always_inline MDBX_DPL mdbx_dpl_sort(MDBX_DPL dl) {
|
static __always_inline MDBX_DPL mdbx_dpl_sort(MDBX_DPL dl) {
|
||||||
assert(dl->length <= MDBX_DPL_TXNFULL);
|
assert(dl->length <= MDBX_DPL_TXNFULL);
|
||||||
assert(dl->sorted <= dl->length);
|
assert(dl->sorted <= dl->length);
|
||||||
@ -3255,8 +3248,7 @@ static __cold __maybe_unused bool mdbx_dirtylist_check(MDBX_txn *txn) {
|
|||||||
if (unlikely(loose != txn->tw.loose_count))
|
if (unlikely(loose != txn->tw.loose_count))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (txn->tw.dirtylist->length - txn->tw.dirtylist->sorted <
|
if (txn->tw.dirtylist->length - txn->tw.dirtylist->sorted < 16) {
|
||||||
SORT_THRESHOLD / 2) {
|
|
||||||
for (unsigned i = 1; i <= MDBX_PNL_SIZE(txn->tw.retired_pages); ++i) {
|
for (unsigned i = 1; i <= MDBX_PNL_SIZE(txn->tw.retired_pages); ++i) {
|
||||||
const MDBX_page *const dp =
|
const MDBX_page *const dp =
|
||||||
mdbx_dpl_find(txn->tw.dirtylist, txn->tw.retired_pages[i]);
|
mdbx_dpl_find(txn->tw.dirtylist, txn->tw.retired_pages[i]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user