Adopted lazy encoding for branch attrs

- LFSR_TAG_BRANCH      -+-> lfsr_data_frombranch
- LFSR_TAG_SHRUBBRANCH -'

This was a bit more involved than the others, since it requires changing
what we store in lfsr_bscratch_t.

I did poke around a bit with trying to reduce the total number of rbyd
allocations in lfsr_btree_commit__, but unfortunately we need both the
sibling rbyds and attr rbyds allocated at the same time while we
recursively figure out how to split/merge/commit.

I also almost forgot to include the dsize estimate, but fortunately this
was caught by our tests. We _do_ need branch dsizes, since they
contribute to any non-inlined bshrub's shrub estimate!

---

This was unfortunately a net-negative. We were actually getting a lot of
value from the smaller encoded branch size:

           code          stack          ctx
  before: 35472           2440          636
  after:  35508 (+0.1%)   2472 (+1.3%)  636 (+0.0%)

It may be worth reverting this, but I want to see how it interacts when
all of the existing eager rattr encoding logic has been removed.
This commit is contained in:
Christopher Haster
2025-02-10 02:04:34 -06:00
parent 4303028c83
commit 9c199ce7c0
+33 -22
View File
@@ -3487,6 +3487,8 @@ static lfsr_data_t lfsr_data_frombtree(const lfsr_btree_t *btree,
uint8_t buffer[static LFSR_BTREE_DSIZE]);
static lfsr_data_t lfsr_data_frommptr(const lfs_block_t mptr[static 2],
uint8_t buffer[static LFSR_MPTR_DSIZE]);
static lfsr_data_t lfsr_data_frombranch(const lfsr_rbyd_t *branch,
uint8_t buffer[static LFSR_BRANCH_DSIZE]);
static int lfsr_rbyd_appendrattr_(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfsr_rattr_t rattr) {
@@ -3520,7 +3522,9 @@ static int lfsr_rbyd_appendrattr_(lfs_t *lfs, lfsr_rbyd_t *rbyd,
LFSR_BTREE_DSIZE,
LFS_MAX(
LFSR_MPTR_DSIZE,
LFSR_ECKSUM_DSIZE)))))))];
LFS_MAX(
LFSR_BRANCH_DSIZE,
LFSR_ECKSUM_DSIZE))))))))];
struct {
lfsr_data_t datas[2];
uint8_t buf[LFSR_LEB128_DSIZE];
@@ -3609,6 +3613,15 @@ static int lfsr_rbyd_appendrattr_(lfs_t *lfs, lfsr_rbyd_t *rbyd,
data_count = size;
break;
// branch?
case LFSR_TAG_BRANCH:;
case LFSR_TAG_SHRUB | LFSR_TAG_BRANCH:;
data = lfsr_data_frombranch(rattr.u.etc, ctx.u.buf);
size = lfsr_data_size(data);
datas = ctx.u.buf;
data_count = size;
break;
// ecksum?
case LFSR_TAG_ECKSUM:;
data = lfsr_data_fromecksum(rattr.u.etc, ctx.u.buf);
@@ -5445,7 +5458,7 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
typedef struct lfsr_bscratch {
lfsr_rattr_t rattrs[4];
lfsr_data_t split_data;
uint8_t buf[2*LFSR_BRANCH_DSIZE];
lfsr_rbyd_t branches[2];
} lfsr_bscratch_t;
// core btree algorithm
@@ -5834,16 +5847,14 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
rattr_count_ = 0;
// new root?
if (!lfsr_rbyd_trunk(&parent)) {
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
bscratch->branches[0] = rbyd__;
bscratch->rattrs[rattr_count_++] = LFSR_RATTR__(
LFSR_TAG_BRANCH, +rbyd__.weight,
LFSR_DATA_BRANCH(
&rbyd__,
&bscratch->buf[0*LFSR_BRANCH_DSIZE]));
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
&bscratch->branches[0], LFSR_BRANCH_DSIZE);
bscratch->branches[1] = sibling;
bscratch->rattrs[rattr_count_++] = LFSR_RATTR__(
LFSR_TAG_BRANCH, +sibling.weight,
LFSR_DATA_BRANCH(
&sibling,
&bscratch->buf[1*LFSR_BRANCH_DSIZE]));
&bscratch->branches[1], LFSR_BRANCH_DSIZE);
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
bscratch->rattrs[rattr_count_++] = LFSR_RATTR_CAT_(
LFSR_TAG_NAME, 0,
@@ -5852,21 +5863,19 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
// split root?
} else {
bid_ -= pid - (rbyd_.weight-1);
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
bscratch->branches[0] = rbyd__;
bscratch->rattrs[rattr_count_++] = LFSR_RATTR__(
LFSR_TAG_BRANCH, 0,
LFSR_DATA_BRANCH(
&rbyd__,
&bscratch->buf[0*LFSR_BRANCH_DSIZE]));
&bscratch->branches[0], LFSR_BRANCH_DSIZE);
if (rbyd__.weight != rbyd_.weight) {
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
LFSR_TAG_GROW, -rbyd_.weight + rbyd__.weight,
LFSR_DATA_NULL());
}
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
bscratch->branches[1] = sibling;
bscratch->rattrs[rattr_count_++] = LFSR_RATTR__(
LFSR_TAG_BRANCH, +sibling.weight,
LFSR_DATA_BRANCH(
&sibling,
&bscratch->buf[1*LFSR_BRANCH_DSIZE]));
&bscratch->branches[1], LFSR_BRANCH_DSIZE);
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
bscratch->rattrs[rattr_count_++] = LFSR_RATTR_CAT_(
LFSR_TAG_NAME, 0,
@@ -5947,9 +5956,10 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
bid_ -= pid - (rbyd_.weight-1);
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
LFSR_TAG_RM, -sibling.weight, LFSR_DATA_NULL());
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
bscratch->branches[0] = rbyd__;
bscratch->rattrs[rattr_count_++] = LFSR_RATTR__(
LFSR_TAG_BRANCH, 0,
LFSR_DATA_BRANCH(&rbyd__, bscratch->buf));
&bscratch->branches[0], LFSR_BRANCH_DSIZE);
if (rbyd__.weight != rbyd_.weight) {
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
LFSR_TAG_GROW, -rbyd_.weight + rbyd__.weight,
@@ -5987,9 +5997,10 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
LFSR_TAG_RM, -rbyd_.weight, LFSR_DATA_NULL());
} else {
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
bscratch->branches[0] = rbyd__;
bscratch->rattrs[rattr_count_++] = LFSR_RATTR__(
LFSR_TAG_BRANCH, 0,
LFSR_DATA_BRANCH(&rbyd__, bscratch->buf));
&bscratch->branches[0], LFSR_BRANCH_DSIZE);
if (rbyd__.weight != rbyd_.weight) {
bscratch->rattrs[rattr_count_++] = LFSR_RATTR(
LFSR_TAG_GROW, -rbyd_.weight + rbyd__.weight,