Adopted lazy encoding for bptr attrs

- LFSR_TAG_BLOCK      -+-> lfsr_data_frombptr
- LFSR_TAG_SHRUBBLOCK -'

This is where lazy attr encoding causes some problems for our shrub
estimate calculation. As a workaround, lfsr_rattr_t includes the
worst-case encoding size (LFSR_BPTR_DSIZE) in the otherwise-unused count
field, which avoids needing a second tag lookup.

This makes our shrub estimate a little bit worse, but is unavoidable
without reencoding bptr attrs.

On the bright side, this led to a bit of simplication in
lfsr_file_carve.

Saves more code and stack:

           code          stack          ctx
  before: 35848           2504          636
  after:  35636 (-0.6%)   2440 (-2.6%)  636 (+0.0%)
This commit is contained in:
Christopher Haster
2025-02-09 15:14:36 -06:00
parent 11c30929e9
commit 3e662e0b52
+49 -46
View File
@@ -3379,6 +3379,8 @@ static int lfsr_rbyd_appendtag(lfs_t *lfs, lfsr_rbyd_t *rbyd,
} }
// needed in lfsr_rbyd_appendrattr_ // needed in lfsr_rbyd_appendrattr_
static lfsr_data_t lfsr_data_frombptr(const lfsr_bptr_t *bptr,
uint8_t buffer[static LFSR_BPTR_DSIZE]);
static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub, static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub,
uint8_t buffer[static LFSR_SHRUB_DSIZE]); uint8_t buffer[static LFSR_SHRUB_DSIZE]);
static lfsr_data_t lfsr_data_frommptr(const lfs_block_t mptr[static 2], static lfsr_data_t lfsr_data_frommptr(const lfs_block_t mptr[static 2],
@@ -3395,21 +3397,33 @@ static int lfsr_rbyd_appendrattr_(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfs_size_t size; lfs_size_t size;
const void *cat; const void *cat;
int16_t count; int16_t count;
// TODO how to organize this? // uh, there's probably a better way to do this, but I'm not sure
// what it is
uint8_t buf[LFS_MAX( uint8_t buf[LFS_MAX(
LFSR_SHRUB_DSIZE, LFSR_BPTR_DSIZE,
LFS_MAX( LFS_MAX(
LFSR_BTREE_DSIZE, LFSR_SHRUB_DSIZE,
LFS_MAX( LFS_MAX(
LFSR_MPTR_DSIZE, LFSR_BTREE_DSIZE,
LFSR_ECKSUM_DSIZE)))]; LFS_MAX(
LFSR_MPTR_DSIZE,
LFSR_ECKSUM_DSIZE))))];
switch ((rattr.count >= 0) ? rattr.tag : LFSR_TAG_NULL) { switch ((rattr.count >= 0) ? rattr.tag : LFSR_TAG_NULL) {
// bptr?
case LFSR_TAG_BLOCK:;
case LFSR_TAG_SHRUB | LFSR_TAG_BLOCK:;
lfsr_data_t data = lfsr_data_frombptr(rattr.cat, buf);
size = lfsr_data_size(data);
cat = buf;
count = size;
break;
// shrub trunk? // shrub trunk?
case LFSR_TAG_BSHRUB:; case LFSR_TAG_BSHRUB:;
// note unlike the other lazy tags, we _need_ to lazily encode // note unlike the other lazy tags, we _need_ to lazily encode
// shrub trunks, since they change underneath us during mdir // shrub trunks, since they change underneath us during mdir
// compactions, relocations, etc // compactions, relocations, etc
lfsr_data_t data = lfsr_data_fromshrub(rattr.cat, buf); data = lfsr_data_fromshrub(rattr.cat, buf);
size = lfsr_data_size(data); size = lfsr_data_size(data);
cat = buf; cat = buf;
count = size; count = size;
@@ -11331,14 +11345,8 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
lfsr_bid_t bid = file->b.shrub.weight; lfsr_bid_t bid = file->b.shrub.weight;
lfsr_rattr_t rattrs[5]; lfsr_rattr_t rattrs[5];
lfs_size_t rattr_count = 0; lfs_size_t rattr_count = 0;
union { lfsr_bptr_t left;
lfsr_data_t data; lfsr_bptr_t right;
uint8_t buf[LFSR_BPTR_DSIZE];
} left;
union {
lfsr_data_t data;
uint8_t buf[LFSR_BPTR_DSIZE];
} right;
// need a hole? // need a hole?
if (pos > file->b.shrub.weight) { if (pos > file->b.shrub.weight) {
@@ -11382,18 +11390,20 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
#endif #endif
// note, an entry can be both a left and right sibling // note, an entry can be both a left and right sibling
lfsr_data_t left_slice_ = LFSR_DATA_SLICE(bptr_.data, left = bptr_;
left.data = LFSR_DATA_SLICE(bptr_.data,
-1, -1,
pos - (bid-(weight_-1))); pos - (bid-(weight_-1)));
lfsr_data_t right_slice_ = LFSR_DATA_SLICE(bptr_.data, right = bptr_;
right.data = LFSR_DATA_SLICE(bptr_.data,
pos+weight - (bid-(weight_-1)), pos+weight - (bid-(weight_-1)),
-1); -1);
// left sibling needs carving but falls underneath our // left sibling needs carving but falls underneath our
// crystallization threshold? break into fragments // crystallization threshold? break into fragments
while (lfsr_bptr_isbptr(&bptr_) while (lfsr_bptr_isbptr(&bptr_)
&& lfsr_data_size(left_slice_) > lfs->cfg->fragment_size && lfsr_data_size(left.data) > lfs->cfg->fragment_size
&& lfsr_data_size(left_slice_) < lfs->cfg->crystal_thresh) { && lfsr_data_size(left.data) < lfs->cfg->crystal_thresh) {
bptr_.data = LFSR_DATA_SLICE(bptr_.data, bptr_.data = LFSR_DATA_SLICE(bptr_.data,
lfs->cfg->fragment_size, lfs->cfg->fragment_size,
-1); -1);
@@ -11402,18 +11412,18 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
LFSR_RATTR_CAT( LFSR_RATTR_CAT(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA, LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
-(weight_ - lfs->cfg->fragment_size), -(weight_ - lfs->cfg->fragment_size),
LFSR_DATA_TRUNCATE(left_slice_, LFSR_DATA_TRUNCATE(left.data,
lfs->cfg->fragment_size)), lfs->cfg->fragment_size)),
LFSR_RATTR( LFSR_RATTR__(
LFSR_TAG_BLOCK, LFSR_TAG_BLOCK,
+(weight_ - lfs->cfg->fragment_size), +(weight_ - lfs->cfg->fragment_size),
LFSR_DATA_BPTR(&bptr_, left.buf)))); &bptr_, LFSR_BPTR_DSIZE)));
if (err) { if (err) {
return err; return err;
} }
weight_ -= lfs->cfg->fragment_size; weight_ -= lfs->cfg->fragment_size;
left_slice_ = LFSR_DATA_SLICE(bptr_.data, left.data = LFSR_DATA_SLICE(bptr_.data,
-1, -1,
pos - (bid-(weight_-1))); pos - (bid-(weight_-1)));
} }
@@ -11421,21 +11431,21 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// right sibling needs carving but falls underneath our // right sibling needs carving but falls underneath our
// crystallization threshold? break into fragments // crystallization threshold? break into fragments
while (lfsr_bptr_isbptr(&bptr_) while (lfsr_bptr_isbptr(&bptr_)
&& lfsr_data_size(right_slice_) > lfs->cfg->fragment_size && lfsr_data_size(right.data) > lfs->cfg->fragment_size
&& lfsr_data_size(right_slice_) < lfs->cfg->crystal_thresh) { && lfsr_data_size(right.data) < lfs->cfg->crystal_thresh) {
bptr_.data = LFSR_DATA_SLICE(bptr_.data, bptr_.data = LFSR_DATA_SLICE(bptr_.data,
-1, -1,
lfsr_data_size(bptr_.data) - lfs->cfg->fragment_size); lfsr_data_size(bptr_.data) - lfs->cfg->fragment_size);
err = lfsr_file_commit(lfs, file, bid, LFSR_RATTRS( err = lfsr_file_commit(lfs, file, bid, LFSR_RATTRS(
LFSR_RATTR( LFSR_RATTR__(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK, LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
-(weight_ - lfsr_data_size(bptr_.data)), -(weight_ - lfsr_data_size(bptr_.data)),
LFSR_DATA_BPTR(&bptr_, right.buf)), &bptr_, LFSR_BPTR_DSIZE),
LFSR_RATTR_CAT( LFSR_RATTR_CAT(
LFSR_TAG_DATA, LFSR_TAG_DATA,
+(weight_ - lfsr_data_size(bptr_.data)), +(weight_ - lfsr_data_size(bptr_.data)),
LFSR_DATA_FRUNCATE(right_slice_, LFSR_DATA_FRUNCATE(right.data,
lfs->cfg->fragment_size)))); lfs->cfg->fragment_size))));
if (err) { if (err) {
return err; return err;
@@ -11443,7 +11453,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
bid -= (weight_-lfsr_data_size(bptr_.data)); bid -= (weight_-lfsr_data_size(bptr_.data));
weight_ -= (weight_-lfsr_data_size(bptr_.data)); weight_ -= (weight_-lfsr_data_size(bptr_.data));
right_slice_ = LFSR_DATA_SLICE(bptr_.data, right.data = LFSR_DATA_SLICE(bptr_.data,
pos+weight - (bid-(weight_-1)), pos+weight - (bid-(weight_-1)),
-1); -1);
} }
@@ -11451,13 +11461,12 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// found left sibling? // found left sibling?
if (bid-(weight_-1) < pos) { if (bid-(weight_-1) < pos) {
// can we get away with a grow attribute? // can we get away with a grow attribute?
if (lfsr_data_size(bptr_.data) == lfsr_data_size(left_slice_)) { if (lfsr_data_size(bptr_.data) == lfsr_data_size(left.data)) {
rattrs[rattr_count++] = LFSR_RATTR( rattrs[rattr_count++] = LFSR_RATTR(
LFSR_TAG_GROW, -(bid+1 - pos), LFSR_DATA_NULL()); LFSR_TAG_GROW, -(bid+1 - pos), LFSR_DATA_NULL());
// carve fragment? // carve fragment?
} else if (!lfsr_bptr_isbptr(&bptr_)) { } else if (!lfsr_bptr_isbptr(&bptr_)) {
left.data = left_slice_;
rattrs[rattr_count++] = LFSR_RATTR_CAT_( rattrs[rattr_count++] = LFSR_RATTR_CAT_(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA, LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
-(bid+1 - pos), -(bid+1 - pos),
@@ -11465,11 +11474,10 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// carve bptr? // carve bptr?
} else { } else {
bptr_.data = left_slice_; rattrs[rattr_count++] = LFSR_RATTR__(
rattrs[rattr_count++] = LFSR_RATTR(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK, LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
-(bid+1 - pos), -(bid+1 - pos),
LFSR_DATA_BPTR(&bptr_, left.buf)); &left, LFSR_BPTR_DSIZE);
} }
// completely overwriting this entry? // completely overwriting this entry?
@@ -11481,7 +11489,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// spans more than one entry? we can't do everything in one commit, // spans more than one entry? we can't do everything in one commit,
// so commit what we have and move on to next entry // so commit what we have and move on to next entry
if (pos+weight > bid+1) { if (pos+weight > bid+1) {
LFS_ASSERT(lfsr_data_size(right_slice_) == 0); LFS_ASSERT(lfsr_data_size(right.data) == 0);
LFS_ASSERT(rattr_count <= sizeof(rattrs)/sizeof(lfsr_rattr_t)); LFS_ASSERT(rattr_count <= sizeof(rattrs)/sizeof(lfsr_rattr_t));
err = lfsr_file_commit(lfs, file, bid, err = lfsr_file_commit(lfs, file, bid,
@@ -11499,24 +11507,20 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// found right sibling? // found right sibling?
if (pos+weight < bid+1) { if (pos+weight < bid+1) {
// can we coalesce a hole? // can we coalesce a hole?
if (lfsr_data_size(right_slice_) == 0) { if (lfsr_data_size(right.data) == 0) {
rattr.weight += bid+1 - (pos+weight); rattr.weight += bid+1 - (pos+weight);
// carve fragment? // carve fragment?
} else if (!lfsr_bptr_isbptr(&bptr_)) { } else if (!lfsr_bptr_isbptr(&bptr_)) {
right.data = right_slice_;
right_rattr_ = LFSR_RATTR_CAT_( right_rattr_ = LFSR_RATTR_CAT_(
LFSR_TAG_DATA, LFSR_TAG_DATA, bid+1 - (pos+weight),
bid+1 - (pos+weight),
&right.data, 1); &right.data, 1);
// carve bptr? // carve bptr?
} else { } else {
bptr_.data = right_slice_; right_rattr_ = LFSR_RATTR__(
right_rattr_ = LFSR_RATTR( LFSR_TAG_BLOCK, bid+1 - (pos+weight),
LFSR_TAG_BLOCK, &right, LFSR_BPTR_DSIZE);
bid+1 - (pos+weight),
LFSR_DATA_BPTR(&bptr_, right.buf));
} }
} }
@@ -11934,12 +11938,11 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
eoff, cksum); eoff, cksum);
// and write it into our tree // and write it into our tree
uint8_t bptr_buf[LFSR_BPTR_DSIZE];
err = lfsr_file_carve(lfs, file, err = lfsr_file_carve(lfs, file,
block_start, block_end - block_start, block_start, block_end - block_start,
LFSR_RATTR( LFSR_RATTR__(
LFSR_TAG_BLOCK, 0, LFSR_TAG_BLOCK, 0,
LFSR_DATA_BPTR(&bptr, bptr_buf))); &bptr, LFSR_BPTR_DSIZE));
if (err) { if (err) {
return err; return err;
} }