Added rbyd < 1/4 block_size condition to btree merges

This just avoids the overhead of estimating our sibling's sizes, which
we don't really want to do every compact.
This commit is contained in:
Christopher Haster
2023-08-20 01:18:05 -05:00
parent bacd09a673
commit 105a0a12ce
+72 -67
View File
@@ -3946,81 +3946,86 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
// before we compact, can we merge with our siblings? // before we compact, can we merge with our siblings?
lfsr_rbyd_t sibling; lfsr_rbyd_t sibling;
for (uint8_t i = 0; i < 2; i++) { if ((lfs_size_t)estimate <= lfs->cfg->block_size/4
lfs_ssize_t sibling_rid; // no parent? can't merge
// try the right sibling && rid != -1) {
if (i == 0) { for (uint8_t i = 0; i < 2; i++) {
sibling_rid = rid+1; 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 // try the left sibling
} else { } else {
sibling_rid = rid-rbyd.weight; sibling_rid = rid-rbyd.weight;
} // no left sibling? can't merge
if (sibling_rid < 0) {
// no parent? no sibling? continue;
if (rid == -1 }
|| sibling_rid < 0
|| sibling_rid >= (lfs_ssize_t)parent.weight) {
continue;
}
// try looking up the sibling
// TODO do we really need to fetch sibling_weight if we get
// it in our btree struct?
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,
&sibling_rid, &sibling_tag, &sibling_weight,
&sibling_data);
if (err) {
// no sibling? can't merge
if (err == LFS_ERR_NOENT) {
continue;
} }
return err;
}
if (sibling_tag == LFSR_TAG_NAME) { // try looking up the sibling
err = lfsr_rbyd_lookup(lfs, &parent, // TODO do we really need to fetch sibling_weight if we get
sibling_rid, LFSR_TAG_WIDE(STRUCT), // it in our btree struct?
&sibling_tag, &sibling_data); 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,
&sibling_rid, &sibling_tag, &sibling_weight,
&sibling_data);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT); // no sibling? can't merge
if (err == LFS_ERR_NOENT) {
continue;
}
return err; return err;
} }
}
LFS_ASSERT(sibling_tag == LFSR_TAG_BRANCH); if (sibling_tag == LFSR_TAG_NAME) {
err = lfsr_data_readbranch(lfs, &sibling_data, sibling_weight, err = lfsr_rbyd_lookup(lfs, &parent,
&sibling); sibling_rid, LFSR_TAG_WIDE(STRUCT),
if (err) { &sibling_tag, &sibling_data);
return err; if (err) {
} LFS_ASSERT(err != LFS_ERR_NOENT);
return err;
// estimate if our sibling will fit }
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs, }
&sibling, -1, -1,
NULL); LFS_ASSERT(sibling_tag == LFSR_TAG_BRANCH);
if (sibling_estimate < 0) { err = lfsr_data_readbranch(lfs, &sibling_data, sibling_weight,
return estimate; &sibling);
} if (err) {
return err;
// fits? try to merge }
if ((lfs_size_t)(estimate + sibling_estimate)
< lfs->cfg->block_size/2) { // estimate if our sibling will fit
if (i == 1) { lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
// if we're merging our left sibling, swap our rbyds &sibling, -1, -1,
// so our sibling is on the right NULL);
bid -= sibling.weight; if (sibling_estimate < 0) {
rid -= rbyd.weight; return estimate;
}
rbyd_ = sibling;
sibling = rbyd; // fits? try to merge
rbyd = rbyd_; 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;
rbyd_ = sibling;
sibling = rbyd;
rbyd = rbyd_;
}
goto merge;
} }
goto merge;
} }
} }