Replaced attr-list datas/buf arrays with union

lfsr_data_t datas[d];   =>  union {
  lfs_size_t data_count;          lfsr_data_t data;
  uint8_t buf[b];                 uint8_t buf[b'];
  lfs_size_t buf_size;        } datas[d+b];
                              lfs_size_t data_count;

This trades off extra bookeeping (data_count + buf_size vs data_count)
for less-tight stack overhead.

But this also saves a significant amount of RAM in lfsr_file_carve,
where we have exclusive fragments/bptrs for our left and right siblings.
So the end stack cost/savings mostly cancel out.

The end result seems like a net benefit for code cost:

           code          stack
  before: 33872           2816
  after:  33796 (-0.2%)   2808 (-0.3%)
This commit is contained in:
Christopher Haster
2024-05-05 15:11:08 -05:00
parent 0509fba9b9
commit 78b92cc954
+54 -56
View File
@@ -4377,8 +4377,10 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
// extra state needed for non-terminating lfsr_btree_commit_ calls // extra state needed for non-terminating lfsr_btree_commit_ calls
typedef struct lfsr_btree_scratch { typedef struct lfsr_btree_scratch {
lfsr_attr_t attrs[4]; lfsr_attr_t attrs[4];
lfsr_data_t datas[1]; union {
uint8_t buf[2*LFSR_BRANCH_DSIZE]; lfsr_data_t data;
uint8_t buf[LFSR_BRANCH_DSIZE];
} datas[3];
} lfsr_btree_scratch_t; } lfsr_btree_scratch_t;
// core btree algorithm // core btree algorithm
@@ -4512,7 +4514,6 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
// end up removing an rbyd here // end up removing an rbyd here
attr_count = 0; attr_count = 0;
lfs_size_t data_count = 0; lfs_size_t data_count = 0;
lfs_size_t buf_size = 0;
bid -= pid - (rbyd.weight-1); bid -= pid - (rbyd.weight-1);
if (rbyd_.weight == 0) { if (rbyd_.weight == 0) {
@@ -4521,8 +4522,9 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
} else { } else {
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BRANCH, 0, LFSR_TAG_BRANCH, 0,
lfsr_cat_frombranch(&rbyd_, &scratch->buf[buf_size])); lfsr_cat_frombranch(
buf_size += LFSR_BRANCH_DSIZE; &rbyd_,
scratch->datas[data_count++].buf));
if (rbyd_.weight != rbyd.weight) { if (rbyd_.weight != rbyd.weight) {
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd.weight + rbyd_.weight, LFSR_TAG_GROW, -rbyd.weight + rbyd_.weight,
@@ -4787,32 +4789,33 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
LFS_ASSERT(sibling.weight > 0); LFS_ASSERT(sibling.weight > 0);
attr_count = 0; attr_count = 0;
data_count = 0; data_count = 0;
buf_size = 0;
// new root? // new root?
if (!lfsr_rbyd_trunk(&parent)) { if (!lfsr_rbyd_trunk(&parent)) {
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BRANCH, +rbyd_.weight, LFSR_TAG_BRANCH, +rbyd_.weight,
lfsr_cat_frombranch(&rbyd_, &scratch->buf[buf_size])); lfsr_cat_frombranch(
buf_size += LFSR_BRANCH_DSIZE; &rbyd_,
scratch->datas[data_count++].buf));
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BRANCH, +sibling.weight, LFSR_TAG_BRANCH, +sibling.weight,
lfsr_cat_frombranch(&sibling, &scratch->buf[buf_size])); lfsr_cat_frombranch(
buf_size += LFSR_BRANCH_DSIZE; &sibling,
scratch->datas[data_count++].buf));
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) { if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
scratch->datas[data_count] = split_data; scratch->datas[data_count].data = split_data;
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_NAME, 0, LFSR_TAG_NAME, 0,
LFSR_CAT_DATA(&scratch->datas[data_count])); LFSR_CAT_DATA(&scratch->datas[data_count++].data));
data_count += 1;
} }
// split root? // split root?
} else { } else {
bid -= pid - (rbyd.weight-1); bid -= pid - (rbyd.weight-1);
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BRANCH, 0, LFSR_TAG_BRANCH, 0,
lfsr_cat_frombranch(&rbyd_, &scratch->buf[buf_size])); lfsr_cat_frombranch(
buf_size += LFSR_BRANCH_DSIZE; &rbyd_,
scratch->datas[data_count++].buf));
if (rbyd_.weight != rbyd.weight) { if (rbyd_.weight != rbyd.weight) {
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd.weight + rbyd_.weight, LFSR_TAG_GROW, -rbyd.weight + rbyd_.weight,
@@ -4820,14 +4823,14 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
} }
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BRANCH, +sibling.weight, LFSR_TAG_BRANCH, +sibling.weight,
lfsr_cat_frombranch(&sibling, &scratch->buf[buf_size])); lfsr_cat_frombranch(
buf_size += LFSR_BRANCH_DSIZE; &sibling,
scratch->datas[data_count++].buf));
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) { if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
scratch->datas[data_count] = split_data; scratch->datas[data_count].data = split_data;
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_NAME, 0, LFSR_TAG_NAME, 0,
LFSR_CAT_DATA(&scratch->datas[data_count])); LFSR_CAT_DATA(&scratch->datas[data_count++].data));
data_count += 1;
} }
} }
attrs = scratch->attrs; attrs = scratch->attrs;
@@ -4891,15 +4894,15 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
LFS_ASSERT(rbyd_.weight > 0); LFS_ASSERT(rbyd_.weight > 0);
attr_count = 0; attr_count = 0;
data_count = 0; data_count = 0;
buf_size = 0;
bid -= pid - (rbyd.weight-1); bid -= pid - (rbyd.weight-1);
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_RM, -sibling.weight, LFSR_CAT_NULL()); LFSR_TAG_RM, -sibling.weight, LFSR_CAT_NULL());
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BRANCH, 0, LFSR_TAG_BRANCH, 0,
lfsr_cat_frombranch(&rbyd_, &scratch->buf[buf_size])); lfsr_cat_frombranch(
buf_size += LFSR_BRANCH_DSIZE; &rbyd_,
scratch->datas[data_count++].buf));
if (rbyd_.weight != rbyd.weight) { if (rbyd_.weight != rbyd.weight) {
scratch->attrs[attr_count++] = LFSR_ATTR( scratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd.weight + rbyd_.weight, LFSR_TAG_GROW, -rbyd.weight + rbyd_.weight,
@@ -10309,10 +10312,11 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
lfsr_bid_t bid = lfsr_bshrub_size(&file->bshrub); lfsr_bid_t bid = lfsr_bshrub_size(&file->bshrub);
lfsr_attr_t attrs[5]; lfsr_attr_t attrs[5];
lfs_size_t attr_count = 0; lfs_size_t attr_count = 0;
lfsr_data_t datas[2]; union {
lfsr_data_t data;
uint8_t buf[LFSR_BPTR_DSIZE];
} datas[2];
lfs_size_t data_count = 0; lfs_size_t data_count = 0;
uint8_t buf[2*LFSR_BPTR_DSIZE];
lfs_size_t buf_size = 0;
// always convert to bshrub/btree when this function is called // always convert to bshrub/btree when this function is called
if (!lfsr_bshrub_isbshruborbtree(&file->bshrub)) { if (!lfsr_bshrub_isbshruborbtree(&file->bshrub)) {
@@ -10326,8 +10330,9 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
} else if (lfsr_bshrub_isbptr(&file->m.mdir, &file->bshrub)) { } else if (lfsr_bshrub_isbptr(&file->m.mdir, &file->bshrub)) {
attrs[attr_count++] = LFSR_ATTR( attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BLOCK, +lfsr_bshrub_size(&file->bshrub), LFSR_TAG_BLOCK, +lfsr_bshrub_size(&file->bshrub),
lfsr_cat_frombptr(&file->bshrub.u.bptr, &buf[buf_size])); lfsr_cat_frombptr(
buf_size += LFSR_BPTR_DSIZE; &file->bshrub.u.bptr,
datas[data_count++].buf));
} }
file->bshrub.u.bshrub.blocks[0] = file->m.mdir.rbyd.blocks[0]; file->bshrub.u.bshrub.blocks[0] = file->m.mdir.rbyd.blocks[0];
@@ -10338,8 +10343,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
if (attr_count > 0) { if (attr_count > 0) {
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t)); LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
LFS_ASSERT(data_count <= sizeof(datas)/sizeof(lfsr_data_t)); LFS_ASSERT(data_count <= sizeof(datas)/sizeof(datas[0]));
LFS_ASSERT(buf_size <= sizeof(buf));
int err = lfsr_bshrub_commit(lfs, file, 0, attrs, attr_count); int err = lfsr_bshrub_commit(lfs, file, 0, attrs, attr_count);
if (err) { if (err) {
@@ -10349,7 +10353,6 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
attr_count = 0; attr_count = 0;
data_count = 0; data_count = 0;
buf_size = 0;
} }
// need a hole? // need a hole?
@@ -10462,12 +10465,11 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// carve fragment? // carve fragment?
} else if (tag_ == LFSR_TAG_DATA) { } else if (tag_ == LFSR_TAG_DATA) {
datas[data_count] = left_slice_; datas[data_count].data = left_slice_;
attrs[attr_count++] = LFSR_ATTR( attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA, LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
-(bid+1 - pos), -(bid+1 - pos),
LFSR_CAT_DATA(&datas[data_count])); LFSR_CAT_DATA(&datas[data_count++].data));
data_count += 1;
// carve bptr? // carve bptr?
} else if (tag_ == LFSR_TAG_BLOCK) { } else if (tag_ == LFSR_TAG_BLOCK) {
@@ -10479,8 +10481,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
.data = left_slice_, .data = left_slice_,
.cksize = bptr_.cksize, .cksize = bptr_.cksize,
.cksum = bptr_.cksum}, .cksum = bptr_.cksum},
&buf[buf_size])); datas[data_count++].buf));
buf_size += LFSR_BPTR_DSIZE;
} else { } else {
LFS_UNREACHABLE(); LFS_UNREACHABLE();
@@ -10497,8 +10498,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
if (pos+weight > bid+1) { if (pos+weight > bid+1) {
LFS_ASSERT(lfsr_data_size(right_slice_) == 0); LFS_ASSERT(lfsr_data_size(right_slice_) == 0);
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t)); LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
LFS_ASSERT(data_count <= sizeof(datas)/sizeof(lfsr_data_t)); LFS_ASSERT(data_count <= sizeof(datas)/sizeof(datas[0]));
LFS_ASSERT(buf_size <= sizeof(buf));
err = lfsr_bshrub_commit(lfs, file, bid, err = lfsr_bshrub_commit(lfs, file, bid,
attrs, attr_count); attrs, attr_count);
@@ -10510,7 +10510,6 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
weight -= lfs_min32(weight, bid+1 - pos); weight -= lfs_min32(weight, bid+1 - pos);
attr_count = 0; attr_count = 0;
data_count = 0; data_count = 0;
buf_size = 0;
continue; continue;
} }
@@ -10572,18 +10571,18 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
if (right_tag_) { if (right_tag_) {
// right fragment? // right fragment?
if (right_tag_ == LFSR_TAG_DATA) { if (right_tag_ == LFSR_TAG_DATA) {
datas[data_count] = right_bptr_.data; datas[data_count].data = right_bptr_.data;
attrs[attr_count++] = LFSR_ATTR( attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_DATA, +right_weight_, LFSR_TAG_DATA, +right_weight_,
LFSR_CAT_DATA(&datas[data_count])); LFSR_CAT_DATA(&datas[data_count++].data));
data_count += 1;
// right bptr? // right bptr?
} else if (right_tag_ == LFSR_TAG_BLOCK) { } else if (right_tag_ == LFSR_TAG_BLOCK) {
attrs[attr_count++] = LFSR_ATTR( attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BLOCK, +right_weight_, LFSR_TAG_BLOCK, +right_weight_,
lfsr_cat_frombptr(&right_bptr_, &buf[buf_size])); lfsr_cat_frombptr(
buf_size += LFSR_BPTR_DSIZE; &right_bptr_,
datas[data_count++].buf));
} else { } else {
LFS_UNREACHABLE(); LFS_UNREACHABLE();
@@ -10593,8 +10592,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// commit pending attrs // commit pending attrs
if (attr_count > 0) { if (attr_count > 0) {
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t)); LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
LFS_ASSERT(data_count <= sizeof(datas)/sizeof(lfsr_data_t)); LFS_ASSERT(data_count <= sizeof(datas)/sizeof(datas[0]));
LFS_ASSERT(buf_size <= sizeof(buf));
int err = lfsr_bshrub_commit(lfs, file, bid, int err = lfsr_bshrub_commit(lfs, file, bid,
attrs, attr_count); attrs, attr_count);
@@ -11412,15 +11410,16 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
// commit our file's metadata // commit our file's metadata
lfsr_attr_t attrs[2]; lfsr_attr_t attrs[2];
lfs_size_t attr_count = 0; lfs_size_t attr_count = 0;
lfsr_data_t datas[1]; union {
lfsr_data_t data;
uint8_t buf[LFSR_BTREE_DSIZE];
} datas[2];
lfs_size_t data_count = 0; lfs_size_t data_count = 0;
uint8_t buf[LFSR_BTREE_DSIZE];
lfs_size_t buf_size = 0;
// not created yet? need to convert orphan to normal file // not created yet? need to convert orphan to normal file
if (lfsr_f_isorphan(file->m.flags)) { if (lfsr_f_isorphan(file->m.flags)) {
err = lfsr_mdir_lookup(lfs, &file->m.mdir, LFSR_TAG_ORPHAN, err = lfsr_mdir_lookup(lfs, &file->m.mdir, LFSR_TAG_ORPHAN,
&datas[data_count]); &datas[data_count].data);
if (err) { if (err) {
// we must have an orphan at this point // we must have an orphan at this point
LFS_ASSERT(err != LFS_ERR_NOENT); LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -11429,8 +11428,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
attrs[attr_count++] = LFSR_ATTR( attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_SUB | LFSR_TAG_REG, 0, LFSR_TAG_SUB | LFSR_TAG_REG, 0,
LFSR_CAT_DATA(&datas[data_count])); LFSR_CAT_DATA(&datas[data_count++].data));
data_count += 1;
} }
// commit the file state // commit the file state
@@ -11454,15 +11452,15 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
} else if (lfsr_bshrub_isbtree(&file->m.mdir, &file->bshrub)) { } else if (lfsr_bshrub_isbtree(&file->m.mdir, &file->bshrub)) {
attrs[attr_count++] = LFSR_ATTR( attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_SUB | LFSR_TAG_BTREE, 0, LFSR_TAG_SUB | LFSR_TAG_BTREE, 0,
lfsr_cat_frombtree(&file->bshrub.u.btree, &buf[buf_size])); lfsr_cat_frombtree(
buf_size += LFSR_BTREE_DSIZE; &file->bshrub.u.btree,
datas[data_count++].buf));
} else { } else {
LFS_UNREACHABLE(); LFS_UNREACHABLE();
} }
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t)); LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
LFS_ASSERT(data_count <= sizeof(datas)/sizeof(lfsr_data_t)); LFS_ASSERT(data_count <= sizeof(datas)/sizeof(datas[0]));
LFS_ASSERT(buf_size <= sizeof(buf));
err = lfsr_mdir_commit(lfs, &file->m.mdir, err = lfsr_mdir_commit(lfs, &file->m.mdir,
attrs, attr_count); attrs, attr_count);