From 3e45fc739df4b68eef28fc18bdf2abe5b6ce3591 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 14 Dec 2023 11:55:23 -0600 Subject: [PATCH] Changed becksum lookup to not re-traverse the whole btree We already get the leaf rbyd as a part of btree lookup, and since ids can't be split across rbyd boundaries, we can be sure any bptr attrs live in the same rbyd. This can be extended to any future bptr attrs. Aside from the small performance gain, this also means we can drop the btree bid+tag lookups. All extra attr lookups to lookup the rbyd first. This saves a bit of code but also avoids a set of issues with the btree semantics where lookupnexting an extra attr can return ENOENT prematurely when on an rbyd boundary. As I'm typing this I realize this means we have no way to iterate over all _tags_ in a btree, only over all _bids_. Fortunately I don't think we will ever need the former. code stack before: 32136 2880 after: 31956 (-0.6%) 2880 (+0.0%) --- lfs.c | 81 +++++++++++++++++-------------------------- tests/test_btree.toml | 42 +++++++++++----------- 2 files changed, 52 insertions(+), 71 deletions(-) diff --git a/lfs.c b/lfs.c index c54fbd01..a2b092e6 100644 --- a/lfs.c +++ b/lfs.c @@ -3863,59 +3863,29 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree, } static int lfsr_btree_lookupnext(lfs_t *lfs, const lfsr_btree_t *btree, - lfsr_bid_t bid, lfsr_tag_t tag, + lfsr_bid_t bid, lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_, lfsr_data_t *data_) { - lfsr_rbyd_t rbyd; - lfsr_srid_t rid; - lfsr_tag_t tag__; - int err = lfsr_btree_lookupnext_(lfs, btree, bid, - bid_, &rbyd, &rid, &tag__, weight_, data_); - if (err) { - return err; - } - - // we need to do a bit of extra work if requested tag is not struct - if (lfsr_tag_key(tag__) != LFSR_TAG_STRUCT) { - err = lfsr_rbyd_lookupnext(lfs, &rbyd, rid, tag, - NULL, &tag__, weight_, data_); - if (err) { - return err; - } - } - - if (tag_) { - *tag_ = tag__; - } - return 0; + return lfsr_btree_lookupnext_(lfs, btree, bid, + bid_, NULL, NULL, tag_, weight_, data_); } static int lfsr_btree_lookup(lfs_t *lfs, const lfsr_btree_t *btree, - lfsr_bid_t bid, lfsr_tag_t tag, + lfsr_bid_t bid, lfsr_tag_t *tag_, lfsr_bid_t *weight_, lfsr_data_t *data_) { lfsr_bid_t bid_; - lfsr_tag_t tag__; - int err = lfsr_btree_lookupnext(lfs, btree, bid, tag, - &bid_, &tag__, weight_, data_); + int err = lfsr_btree_lookupnext(lfs, btree, bid, + &bid_, tag_, weight_, data_); if (err) { return err; } - // lookup finds the next-smallest tag, all we need to do is fail if it - // picks up the wrong tag - // - // we accept either exact matches or suptype matches depending on the - // wide bit - if (bid_ != bid - || (lfsr_tag_iswide(tag) - ? lfsr_tag_suptype(tag__) != (tag & ~LFSR_TAG_WIDE) - : tag__ != tag)) { + // lookup finds the next-smallest bid, all we need to do is fail if it + // picks up the wrong bid + if (bid_ != bid) { return LFS_ERR_NOENT; } - if (tag_) { - *tag_ = tag__; - } return 0; } @@ -4791,22 +4761,32 @@ static int lfsr_bshrub_fetch(lfs_t *lfs, return 0; } +static int lfsr_bshrub_lookupnext_(lfs_t *lfs, + const lfsr_mdir_t *mdir, const lfsr_bshrub_t *bshrub, + lfsr_bid_t bid, + lfsr_bid_t *bid_, lfsr_rbyd_t *rbyd_, lfsr_srid_t *rid_, + lfsr_tag_t *tag_, lfsr_bid_t *weight_, lfsr_data_t *data_) { + (void)mdir; + return lfsr_btree_lookupnext_(lfs, &bshrub->rbyd, bid, + bid_, rbyd_, rid_, tag_, weight_, data_); +} + static int lfsr_bshrub_lookupnext(lfs_t *lfs, const lfsr_mdir_t *mdir, const lfsr_bshrub_t *bshrub, - lfsr_bid_t bid, lfsr_tag_t tag, + lfsr_bid_t bid, lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_, lfsr_data_t *data_) { (void)mdir; - return lfsr_btree_lookupnext(lfs, &bshrub->rbyd, bid, tag, + return lfsr_btree_lookupnext(lfs, &bshrub->rbyd, bid, bid_, tag_, weight_, data_); } static int lfsr_bshrub_lookup(lfs_t *lfs, const lfsr_mdir_t *mdir, const lfsr_bshrub_t *bshrub, - lfsr_bid_t bid, lfsr_tag_t tag, + lfsr_bid_t bid, lfsr_tag_t *tag_, lfsr_bid_t *weight_, lfsr_data_t *data_) { (void)mdir; - return lfsr_btree_lookup(lfs, &bshrub->rbyd, bid, tag, + return lfsr_btree_lookup(lfs, &bshrub->rbyd, bid, tag_, weight_, data_); } @@ -5495,7 +5475,7 @@ static int lfsr_mtree_lookup(lfs_t *lfs, lfsr_smid_t mid, lfsr_tag_t tag; lfsr_data_t data; int err = lfsr_btree_lookupnext(lfs, &lfs->mtree.u.btree, - mid, LFSR_TAG_STRUCT, + mid, &bid, &tag, NULL, &data); if (err) { return err; @@ -9360,12 +9340,14 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs, // bshrub/btree? } else { lfsr_bid_t bid; + lfsr_rbyd_t rbyd; + lfsr_srid_t rid; lfsr_tag_t tag; lfsr_bid_t weight; lfsr_data_t data; - int err = lfsr_bshrub_lookupnext(lfs, mdir, &ftree->u.bshrub, - pos, LFSR_TAG_STRUCT, - &bid, &tag, &weight, &data); + int err = lfsr_bshrub_lookupnext_(lfs, mdir, &ftree->u.bshrub, + pos, + &bid, &rbyd, &rid, &tag, &weight, &data); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -9396,9 +9378,8 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs, } if (becksum_) { // need an extra lookup to find becksums - err = lfsr_bshrub_lookup(lfs, mdir, &ftree->u.bshrub, - bid, LFSR_TAG_BECKSUM, - NULL, NULL, &data); + err = lfsr_rbyd_lookup(lfs, &rbyd, rid, LFSR_TAG_BECKSUM, + NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } diff --git a/tests/test_btree.toml b/tests/test_btree.toml index 2e81d1d0..c6653d08 100644 --- a/tests/test_btree.toml +++ b/tests/test_btree.toml @@ -15,7 +15,7 @@ code = ''' lfsr_tag_t *tag_, lfs_size_t *weight_, void *buffer, lfs_size_t size) { lfsr_data_t data; - int err = lfsr_btree_lookup(lfs, btree, bid, LFSR_TAG_STRUCT, + int err = lfsr_btree_lookup(lfs, btree, bid, tag_, weight_, &data); if (err) { return err; @@ -40,7 +40,7 @@ code = ''' // lookup weight to compute deltas lfs_size_t weight_; - int err = lfsr_btree_lookupnext(lfs, btree, bid, LFSR_TAG_STRUCT, + int err = lfsr_btree_lookupnext(lfs, btree, bid, NULL, NULL, &weight_, NULL); if (err) { return err; @@ -60,7 +60,7 @@ code = ''' // lookup weight to compute deltas lfs_size_t weight_; - int err = lfsr_btree_lookupnext(lfs, btree, bid, LFSR_TAG_STRUCT, + int err = lfsr_btree_lookupnext(lfs, btree, bid, NULL, NULL, &weight_, NULL); if (err) { return err; @@ -79,7 +79,7 @@ code = ''' // lookup weight to compute deltas lfs_size_t weight_; - int err = lfsr_btree_lookupnext(lfs, btree, bid, LFSR_TAG_STRUCT, + int err = lfsr_btree_lookupnext(lfs, btree, bid, NULL, NULL, &weight_, NULL); if (err) { return err; @@ -630,7 +630,7 @@ code = ''' lfs_size_t bid_ = -1; lfsr_data_t data_; for (lfs_size_t i = 0; i < n; i++) { - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == i*W+W-1); assert(tag_ == LFSR_TAG_DATA); @@ -639,7 +639,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; ''' @@ -767,7 +767,7 @@ code = ''' weighted_bid += sim_weights[j]; } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == weighted_bid+sim_weights[i]-1); assert(tag_ == LFSR_TAG_DATA); @@ -776,7 +776,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, &sim[i], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim @@ -1186,7 +1186,7 @@ code = ''' lfs_size_t bid_ = -1; lfsr_data_t data_; for (lfs_size_t i = 0; i < N; i++) { - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == i*W+W-1); assert(tag_ == LFSR_TAG_DATA); @@ -1195,7 +1195,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, &uppers[i % 26], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; ''' @@ -1334,7 +1334,7 @@ code = ''' weighted_bid += sim_weights[j]; } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == weighted_bid+sim_weights[i]-1); assert(tag_ == LFSR_TAG_DATA); @@ -1343,7 +1343,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, &sim[i], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim @@ -2005,7 +2005,7 @@ code = ''' lfs_size_t bid_ = -1; lfsr_data_t data_; for (lfs_size_t i = 0; i < REMAINING; i++) { - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == i*W+W-1); assert(tag_ == LFSR_TAG_DATA); @@ -2015,7 +2015,7 @@ code = ''' assert(memcmp(buffer, &alphas[i % 26], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == REMAINING*W+W-1); assert(tag_ == LFSR_TAG_DATA); @@ -2024,7 +2024,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, "R", 1) == 0); - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; ''' @@ -2176,7 +2176,7 @@ code = ''' weighted_bid += sim_weights[j]; } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == weighted_bid+sim_weights[i]-1); assert(tag_ == LFSR_TAG_DATA); @@ -2185,7 +2185,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, &sim[i], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim @@ -2558,7 +2558,7 @@ code = ''' weighted_bid += sim_weights[j]; } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == weighted_bid+sim_weights[i]-1); assert(tag_ == LFSR_TAG_DATA); @@ -2567,7 +2567,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, &sim[i], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim @@ -3114,7 +3114,7 @@ code = ''' weighted_bid += sim_weights[j]; } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => 0; assert(bid_ == weighted_bid+sim_weights[i]-1); assert(tag_ == LFSR_TAG_DATA); @@ -3123,7 +3123,7 @@ code = ''' lfsr_data_read(&lfs, &data_, buffer, 4) => 1; assert(memcmp(buffer, &sim[i], 1) == 0); } - lfsr_btree_lookupnext(&lfs, &btree, bid_+1, LFSR_TAG_STRUCT, + lfsr_btree_lookupnext(&lfs, &btree, bid_+1, &bid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT; // clean up sim