mdbx: minor refine/speedup mdbx_node_search().

Change-Id: Ie3dd42de25e37bff177018cd15108b97cfcb049c
This commit is contained in:
Leonid Yuriev 2020-01-26 18:00:35 +03:00
parent 898b6ee433
commit a8c5daf46a

View File

@ -9960,87 +9960,91 @@ static int __hot mdbx_cmp_memnr(const MDBX_val *a, const MDBX_val *b) {
* If no entry larger or equal to the key is found, returns NULL. */ * If no entry larger or equal to the key is found, returns NULL. */
static MDBX_node *__hot mdbx_node_search(MDBX_cursor *mc, MDBX_val *key, static MDBX_node *__hot mdbx_node_search(MDBX_cursor *mc, MDBX_val *key,
int *exactp) { int *exactp) {
int low, high;
int rc = 0;
MDBX_page *mp = mc->mc_pg[mc->mc_top]; MDBX_page *mp = mc->mc_pg[mc->mc_top];
MDBX_node *node = nullptr; const int nkeys = page_numkeys(mp);
MDBX_val nodekey;
MDBX_cmp_func *cmp;
DKBUF; DKBUF;
const unsigned nkeys = page_numkeys(mp);
mdbx_debug("searching %u keys in %s %spage %" PRIaPGNO, nkeys, mdbx_debug("searching %u keys in %s %spage %" PRIaPGNO, nkeys,
IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "", IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "",
mp->mp_pgno); mp->mp_pgno);
low = IS_LEAF(mp) ? 0 : 1; int low = IS_LEAF(mp) ? 0 : 1;
high = nkeys - 1; int high = nkeys - 1;
cmp = mc->mc_dbx->md_cmp; *exactp = 0;
if (unlikely(high < low)) {
mc->mc_ki[mc->mc_top] = 0;
return NULL;
}
/* Branch pages have no data, so if using integer keys, int rc = 0, i = 0;
* alignment is guaranteed. Use faster mdbx_cmp_int_align4(). */ MDBX_cmp_func *cmp = mc->mc_dbx->md_cmp;
if (cmp == mdbx_cmp_int_align2 && IS_BRANCH(mp)) MDBX_val nodekey;
cmp = mdbx_cmp_int_align4; if (unlikely(IS_LEAF2(mp))) {
unsigned i = 0;
if (IS_LEAF2(mp)) {
mdbx_cassert(mc, mp->mp_leaf2_ksize == mc->mc_db->md_xsize); mdbx_cassert(mc, mp->mp_leaf2_ksize == mc->mc_db->md_xsize);
nodekey.iov_len = mp->mp_leaf2_ksize; nodekey.iov_len = mp->mp_leaf2_ksize;
node = (MDBX_node *)(intptr_t)-1; /* fake */ do {
while (low <= high) {
i = (low + high) >> 1; i = (low + high) >> 1;
nodekey.iov_base = page_leaf2key(mp, i, nodekey.iov_len); nodekey.iov_base = page_leaf2key(mp, i, nodekey.iov_len);
mdbx_cassert(mc, (char *)mp + mc->mc_txn->mt_env->me_psize >= mdbx_cassert(mc, (char *)mp + mc->mc_txn->mt_env->me_psize >=
(char *)nodekey.iov_base + nodekey.iov_len); (char *)nodekey.iov_base + nodekey.iov_len);
rc = cmp(key, &nodekey); rc = cmp(key, &nodekey);
mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc); mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc);
if (rc == 0) if (unlikely(rc == 0)) {
*exactp = 1;
break; break;
if (rc > 0) }
low = i + 1; low = (rc < 0) ? low : i + 1;
else high = (rc < 0) ? i - 1 : high;
high = i - 1; } while (likely(low <= high));
}
} else {
while (low <= high) {
i = (low + high) >> 1;
node = page_node(mp, i); /* Found entry is less than the key. */
nodekey.iov_len = node_ks(node); /* Skip to get the smallest entry larger than key. */
nodekey.iov_base = node_key(node); i += rc > 0;
mdbx_cassert(mc, (char *)mp + mc->mc_txn->mt_env->me_psize >=
(char *)nodekey.iov_base + nodekey.iov_len);
rc = cmp(key, &nodekey); /* store the key index */
if (IS_LEAF(mp)) mc->mc_ki[mc->mc_top] = (indx_t)i;
mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc); return (i < nkeys)
else ? /* fake for LEAF2 */ (MDBX_node *)(intptr_t)-1
mdbx_debug("found branch index %u [%s -> %" PRIaPGNO "], rc = %i", i, : /* There is no entry larger or equal to the key. */ NULL;
DKEY(&nodekey), node_pgno(node), rc);
if (rc == 0)
break;
if (rc > 0)
low = i + 1;
else
high = i - 1;
}
} }
if (rc > 0) /* Found entry is less than the key. */ if (cmp == mdbx_cmp_int_align2 && IS_BRANCH(mp))
i++; /* Skip to get the smallest entry larger than key. */ /* Branch pages have no data, so if using integer keys,
* alignment is guaranteed. Use faster mdbx_cmp_int_align4(). */
cmp = mdbx_cmp_int_align4;
MDBX_node *node;
do {
i = (low + high) >> 1;
node = page_node(mp, i);
nodekey.iov_len = node_ks(node);
nodekey.iov_base = node_key(node);
mdbx_cassert(mc, (char *)mp + mc->mc_txn->mt_env->me_psize >=
(char *)nodekey.iov_base + nodekey.iov_len);
rc = cmp(key, &nodekey);
if (IS_LEAF(mp))
mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc);
else
mdbx_debug("found branch index %u [%s -> %" PRIaPGNO "], rc = %i", i,
DKEY(&nodekey), node_pgno(node), rc);
if (unlikely(rc == 0)) {
*exactp = 1;
break;
}
low = (rc < 0) ? low : i + 1;
high = (rc < 0) ? i - 1 : high;
} while (likely(low <= high));
/* Found entry is less than the key. */
/* Skip to get the smallest entry larger than key. */
i += rc > 0;
if (exactp)
*exactp = (rc == 0 && nkeys > 0);
/* store the key index */ /* store the key index */
mdbx_cassert(mc, i <= UINT16_MAX);
mc->mc_ki[mc->mc_top] = (indx_t)i; mc->mc_ki[mc->mc_top] = (indx_t)i;
if (i >= nkeys) return (i < nkeys) ? page_node(mp, i)
/* There is no entry larger or equal to the key. */ : /* There is no entry larger or equal to the key. */ NULL;
return NULL;
/* page_node is fake for LEAF2 */
return IS_LEAF2(mp) ? node : page_node(mp, i);
} }
#if 0 /* unused for now */ #if 0 /* unused for now */
@ -10758,8 +10762,11 @@ static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
int rc; int rc;
MDBX_page *mp; MDBX_page *mp;
MDBX_node *node = NULL; MDBX_node *node = NULL;
int stub_exactp;
DKBUF; DKBUF;
exactp = exactp ? exactp : &stub_exactp;
if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) && if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) &&
unlikely(key->iov_len != sizeof(uint32_t) && unlikely(key->iov_len != sizeof(uint32_t) &&
key->iov_len != sizeof(uint64_t))) { key->iov_len != sizeof(uint64_t))) {
@ -10792,8 +10799,7 @@ static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
/* Probably happens rarely, but first node on the page /* Probably happens rarely, but first node on the page
* was the one we wanted. */ * was the one we wanted. */
mc->mc_ki[mc->mc_top] = 0; mc->mc_ki[mc->mc_top] = 0;
if (exactp) *exactp = 1;
*exactp = 1;
goto set1; goto set1;
} }
if (rc > 0) { if (rc > 0) {
@ -10811,8 +10817,7 @@ static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
/* last node was the one we wanted */ /* last node was the one we wanted */
mdbx_cassert(mc, nkeys >= 1 && nkeys <= UINT16_MAX + 1); mdbx_cassert(mc, nkeys >= 1 && nkeys <= UINT16_MAX + 1);
mc->mc_ki[mc->mc_top] = (indx_t)(nkeys - 1); mc->mc_ki[mc->mc_top] = (indx_t)(nkeys - 1);
if (exactp) *exactp = 1;
*exactp = 1;
goto set1; goto set1;
} }
if (rc < 0) { if (rc < 0) {
@ -10828,8 +10833,7 @@ static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
rc = mc->mc_dbx->md_cmp(key, &nodekey); rc = mc->mc_dbx->md_cmp(key, &nodekey);
if (rc == 0) { if (rc == 0) {
/* current node was the one we wanted */ /* current node was the one we wanted */
if (exactp) *exactp = 1;
*exactp = 1;
goto set1; goto set1;
} }
} }
@ -10853,7 +10857,7 @@ static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
if (!mc->mc_top) { if (!mc->mc_top) {
/* There are no other pages */ /* There are no other pages */
mc->mc_ki[mc->mc_top] = 0; mc->mc_ki[mc->mc_top] = 0;
if (op == MDBX_SET_RANGE && !exactp) { if (op == MDBX_SET_RANGE && exactp == &stub_exactp) {
rc = 0; rc = 0;
goto set1; goto set1;
} else } else
@ -10872,7 +10876,7 @@ static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
set2: set2:
node = mdbx_node_search(mc, key, exactp); node = mdbx_node_search(mc, key, exactp);
if (exactp != NULL && !*exactp) { if (exactp != &stub_exactp && !*exactp) {
/* MDBX_SET specified and not an exact match. */ /* MDBX_SET specified and not an exact match. */
return MDBX_NOTFOUND; return MDBX_NOTFOUND;
} }