Unrolled the sibling estimate loop in btree merge
This simplifies control flow at a code cost. Unrolling for now as it
avoids all of the iteration derived special handling (which obscures the
underlying logic) and it may be possible to recoup the code cost through
more shared branch utility functions.
code stack
before: 20650 1712
after: 20742 (+0.4%) 1712 (+0.0%)
May revert in the future.
This commit is contained in:
@@ -3952,40 +3952,21 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
if ((lfs_size_t)estimate <= lfs->cfg->block_size/4
|
||||
// no parent? can't merge
|
||||
&& rid != -1) {
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
lfs_ssize_t sibling_rid;
|
||||
// try the right sibling
|
||||
if (i == 0) {
|
||||
sibling_rid = rid+1;
|
||||
// no right sibling? can't merge
|
||||
if (sibling_rid >= (lfs_ssize_t)parent.weight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// try the left sibling
|
||||
} else {
|
||||
sibling_rid = rid-rbyd.weight;
|
||||
// no left sibling? can't merge
|
||||
if (sibling_rid < 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// try the right sibling
|
||||
if (rid+1 < (lfs_ssize_t)parent.weight) {
|
||||
// try looking up the sibling
|
||||
// TODO do we really need to fetch sibling_weight if we get
|
||||
// it in our btree struct?
|
||||
lfs_ssize_t sibling_rid;
|
||||
lfsr_tag_t sibling_tag;
|
||||
lfs_size_t sibling_weight;
|
||||
lfsr_data_t sibling_data;
|
||||
err = lfsr_rbyd_lookupnext(lfs, &parent,
|
||||
sibling_rid, LFSR_TAG_NAME,
|
||||
rid+1, LFSR_TAG_NAME,
|
||||
&sibling_rid, &sibling_tag, &sibling_weight,
|
||||
&sibling_data);
|
||||
if (err) {
|
||||
// no sibling? can't merge
|
||||
if (err == LFS_ERR_NOENT) {
|
||||
continue;
|
||||
}
|
||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -4011,22 +3992,71 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
&sibling, -1, -1,
|
||||
NULL);
|
||||
if (sibling_estimate < 0) {
|
||||
return estimate;
|
||||
return sibling_estimate;
|
||||
}
|
||||
|
||||
// fits? try to merge
|
||||
if ((lfs_size_t)(estimate + sibling_estimate)
|
||||
< lfs->cfg->block_size/2) {
|
||||
if (i == 1) {
|
||||
// if we're merging our left sibling, swap our rbyds
|
||||
// so our sibling is on the right
|
||||
bid -= sibling.weight;
|
||||
rid -= rbyd.weight;
|
||||
goto merge;
|
||||
}
|
||||
}
|
||||
|
||||
rbyd_ = sibling;
|
||||
sibling = rbyd;
|
||||
rbyd = rbyd_;
|
||||
// try the left sibling
|
||||
if (rid-(lfs_ssize_t)rbyd.weight >= 0) {
|
||||
// try looking up the sibling
|
||||
// TODO do we really need to fetch sibling_weight if we get
|
||||
// it in our btree struct?
|
||||
lfs_ssize_t sibling_rid;
|
||||
lfsr_tag_t sibling_tag;
|
||||
lfs_size_t sibling_weight;
|
||||
lfsr_data_t sibling_data;
|
||||
err = lfsr_rbyd_lookupnext(lfs, &parent,
|
||||
rid-rbyd.weight, LFSR_TAG_NAME,
|
||||
&sibling_rid, &sibling_tag, &sibling_weight,
|
||||
&sibling_data);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (sibling_tag == LFSR_TAG_NAME) {
|
||||
err = lfsr_rbyd_lookup(lfs, &parent,
|
||||
sibling_rid, LFSR_TAG_WIDE(STRUCT),
|
||||
&sibling_tag, &sibling_data);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
LFS_ASSERT(sibling_tag == LFSR_TAG_BRANCH);
|
||||
err = lfsr_data_readbranch(lfs, &sibling_data, sibling_weight,
|
||||
&sibling);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// estimate if our sibling will fit
|
||||
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
|
||||
&sibling, -1, -1,
|
||||
NULL);
|
||||
if (sibling_estimate < 0) {
|
||||
return sibling_estimate;
|
||||
}
|
||||
|
||||
// fits? try to merge
|
||||
if ((lfs_size_t)(estimate + sibling_estimate)
|
||||
< lfs->cfg->block_size/2) {
|
||||
// if we're merging our left sibling, swap our rbyds
|
||||
// so our sibling is on the right
|
||||
bid -= sibling.weight;
|
||||
rid -= rbyd.weight;
|
||||
|
||||
rbyd_ = sibling;
|
||||
sibling = rbyd;
|
||||
rbyd = rbyd_;
|
||||
|
||||
goto merge;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user