Added btree/branch fetch functions

These weren't really necessary when btree/branch fetch was nothing more
than tag decoding, but now that we have ckfetches it makes sense to
deduplicate things for a bit of code savings.

One reason I was punting on this was I wasn't really sure if btree/
branch fetch should take decoded fields or the raw lfsr_data_t. We don't
get any code savings with the former, but it's the only API that's
consistent with lfsr_mdir_fetch/lfsr_rbyd_fetch/etc. I was going to go
with lfsr_btree_fetch/fetch_, but fortunately shoving the latter into
the lfsr_data_* namespace solved this dilemma:

- lfsr_branch_fetch     - fetches from decoded fields
- lfsr_data_fetchbranch - fetches from raw data + weight
- lfsr_btree_fetch      - fetches from decoded fields
- lfsr_data_fetchbtree  - fetches from raw data

Unfortunately, lfsr_btree_parent creates a bit of a wrinkle. We don't
want to redundantly fetch the child we're looking for, so we need to
decode and fetch in separate steps. This prevents inlining between these
small functions that could otherwise take place.

And, while they do save a bit of code, the position of these fetch
functions in the stack hot-path end up increasing our total stack
usage when ckfetches are enabled:

                     code          stack
  default before:   36428           2680
  default after:    36456 (+0.1%)   2680 (+0.0%)

  ckfetches before: 36848           2680
  ckfetches after:  36686 (-0.4%)   2712 (+1.2%)

But maybe this is just indicative of us not accounting for
shrinkwrapping?
This commit is contained in:
Christopher Haster
2024-08-14 13:58:00 -05:00
parent a53151df1f
commit 3b1b571d5c
+87 -125
View File
@@ -4706,8 +4706,8 @@ static lfsr_data_t lfsr_data_frombranch(const lfsr_rbyd_t *branch,
return LFSR_DATA_BUF(buffer, d);
}
static int lfsr_data_readbranch(lfs_t *lfs, lfsr_data_t *data,
lfsr_bid_t weight,
static int lfsr_data_readbranch(lfs_t *lfs,
lfsr_data_t *data, lfsr_bid_t weight,
lfsr_rbyd_t *branch) {
// setting off to 0 here will trigger asserts if we try to append
// without fetching first
@@ -4732,6 +4732,52 @@ static int lfsr_data_readbranch(lfs_t *lfs, lfsr_data_t *data,
return 0;
}
// needed in lfsr_branch_fetch
#ifdef LFS_CKFETCHES
static inline bool lfsr_m_isckfetches(uint32_t flags);
#endif
static int lfsr_branch_fetch(lfs_t *lfs, lfsr_rbyd_t *branch,
lfs_block_t block, lfs_size_t trunk, lfsr_bid_t weight,
uint32_t cksum) {
(void)lfs;
branch->blocks[0] = block;
branch->trunk = trunk;
branch->weight = weight;
branch->eoff = 0;
branch->cksum = cksum;
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
int err = lfsr_rbyd_fetchck(lfs, branch,
branch->blocks[0], lfsr_rbyd_trunk(branch),
branch->cksum);
if (err) {
return err;
}
LFS_ASSERT(branch->weight == weight);
}
#endif
return 0;
}
static int lfsr_data_fetchbranch(lfs_t *lfs,
lfsr_data_t *data, lfsr_bid_t weight,
lfsr_rbyd_t *branch) {
// decode branch and fetch
int err = lfsr_data_readbranch(lfs, data, weight,
branch);
if (err) {
return err;
}
return lfsr_branch_fetch(lfs, branch,
branch->blocks[0], branch->trunk, branch->weight,
branch->cksum);
}
// btree on-disk encoding
//
@@ -4794,10 +4840,28 @@ static int lfsr_data_readbtree(lfs_t *lfs, lfsr_data_t *data,
// core btree operations
// needed in lfsr_btree_lookupnext_
#ifdef LFS_CKFETCHES
static inline bool lfsr_m_isckfetches(uint32_t flags);
#endif
static int lfsr_btree_fetch(lfs_t *lfs, lfsr_btree_t *btree,
lfs_block_t block, lfs_size_t trunk, lfsr_bid_t weight,
uint32_t cksum) {
// btree/branch fetch really are the same once we know the weight
return lfsr_branch_fetch(lfs, btree,
block, trunk, weight,
cksum);
}
static int lfsr_data_fetchbtree(lfs_t *lfs, lfsr_data_t *data,
lfsr_btree_t *btree) {
// decode btree and fetch
int err = lfsr_data_readbtree(lfs, data,
btree);
if (err) {
return err;
}
return lfsr_btree_fetch(lfs, btree,
btree->blocks[0], btree->trunk, btree->weight,
btree->cksum);
}
static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree,
lfsr_bid_t bid,
@@ -4833,23 +4897,12 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree,
rid -= (rid__ - (weight__-1));
// fetch the next branch
err = lfsr_data_readbranch(lfs, &data__, weight__, &branch);
err = lfsr_data_fetchbranch(lfs, &data__, weight__,
&branch);
if (err) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &branch,
branch.blocks[0], lfsr_rbyd_trunk(&branch),
branch.cksum);
if (err) {
return err;
}
}
#endif
// found our bid
} else {
// TODO how many of these should be conditional?
@@ -4963,17 +5016,12 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
return 0;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &branch_,
branch_.blocks[0], lfsr_rbyd_trunk(&branch_),
branch_.cksum);
if (err) {
return err;
}
err = lfsr_branch_fetch(lfs, &branch_,
branch_.blocks[0], branch_.trunk, branch_.weight,
branch_.cksum);
if (err) {
return err;
}
#endif
branch = branch_;
}
@@ -5140,24 +5188,12 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
}
LFS_ASSERT(sibling_tag == LFSR_TAG_BRANCH);
err = lfsr_data_readbranch(lfs, &sibling_data, sibling_weight,
err = lfsr_data_fetchbranch(lfs, &sibling_data, sibling_weight,
&sibling);
if (err) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &sibling,
sibling.blocks[0], lfsr_rbyd_trunk(&sibling),
sibling.cksum);
if (err) {
return err;
}
}
#endif
// estimate if our sibling will fit
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
&sibling, -1, -1,
@@ -5200,24 +5236,12 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
}
LFS_ASSERT(sibling_tag == LFSR_TAG_BRANCH);
err = lfsr_data_readbranch(lfs, &sibling_data, sibling_weight,
err = lfsr_data_fetchbranch(lfs, &sibling_data, sibling_weight,
&sibling);
if (err) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &sibling,
sibling.blocks[0], lfsr_rbyd_trunk(&sibling),
sibling.cksum);
if (err) {
return err;
}
}
#endif
// estimate if our sibling will fit
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
&sibling, -1, -1,
@@ -5655,23 +5679,12 @@ static lfs_scmp_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
bid += rid__ - (weight__-1);
// fetch the next branch
err = lfsr_data_readbranch(lfs, &data__, weight__, &branch);
err = lfsr_data_fetchbranch(lfs, &data__, weight__,
&branch);
if (err < 0) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &branch,
branch.blocks[0], lfsr_rbyd_trunk(&branch),
branch.cksum);
if (err < 0) {
return err;
}
}
#endif
// found our rid
} else {
// TODO how many of these should be conditional?
@@ -5763,25 +5776,11 @@ static int lfsr_btree_traverse(lfs_t *lfs, const lfsr_btree_t *btree,
bt->rid -= (rid__ - (weight__-1));
// fetch the next branch
err = lfsr_data_readbranch(lfs, &data__, weight__,
err = lfsr_data_fetchbranch(lfs, &data__, weight__,
&bt->rbyd);
if (err) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &bt->rbyd,
bt->rbyd.blocks[0], lfsr_rbyd_trunk(&bt->rbyd),
bt->rbyd.cksum);
if (err) {
return err;
}
}
#endif
LFS_ASSERT((lfsr_bid_t)bt->rbyd.weight == weight__);
bt->branch = &bt->rbyd;
// return inner btree nodes if this is the first time we've
@@ -9264,24 +9263,12 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t,
// found an mtree?
} else if (tag == LFSR_TAG_MTREE) {
// fetch the root of the mtree
err = lfsr_data_readbtree(lfs, &data, &t->o.bshrub.u.btree);
err = lfsr_data_fetchbtree(lfs, &data,
&t->o.bshrub.u.btree);
if (err) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &t->o.bshrub.u.btree,
t->o.bshrub.u.btree.blocks[0],
lfsr_rbyd_trunk(&t->o.bshrub.u.btree),
t->o.bshrub.u.btree.cksum);
if (err) {
return err;
}
}
#endif
// transition to traversing the mtree
t->u.bt = LFSR_BTRAVERSAL();
t->o.o.flags = lfsr_t_settstate(t->o.o.flags,
@@ -9357,25 +9344,12 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t,
// found a btree?
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
err = lfsr_data_readbtree(lfs, &data,
err = lfsr_data_fetchbtree(lfs, &data,
&t->o.bshrub.u.btree);
if (err) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &t->o.bshrub.u.btree,
t->o.bshrub.u.btree.blocks[0],
lfsr_rbyd_trunk(&t->o.bshrub.u.btree),
t->o.bshrub.u.btree.cksum);
if (err) {
return err;
}
}
#endif
// no? next we need to check any opened files
} else {
t->ot = lfs->omdirs;
@@ -10832,23 +10806,11 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
// or a btree
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
err = lfsr_data_readbtree(lfs, &data, &file->o.bshrub.u.btree);
err = lfsr_data_fetchbtree(lfs, &data,
&file->o.bshrub.u.btree);
if (err) {
return err;
}
#ifdef LFS_CKFETCHES
// checking fetches?
if (lfsr_m_isckfetches(lfs->flags)) {
err = lfsr_rbyd_fetchck(lfs, &file->o.bshrub.u.btree,
file->o.bshrub.u.btree.blocks[0],
lfsr_rbyd_trunk(&file->o.bshrub.u.btree),
file->o.bshrub.u.btree.cksum);
if (err) {
return err;
}
}
#endif
}
}
}