Tried to dedup bptr/data fetching

Like the bshrub/btree dedup, this add lfs3_bptr_fetch to help dedup
bptr/data fetching.

The original plan was to eliminate bptrs from lfs3_file_lookupnext and
lfs3_file_traverse, and just return tagged data like the other
lookup/traverse functions. But this didn't work out very well. We return
arbitrary attrs from lfs3_file_traverse, so all this would've
accomplished is making every lfs3_file_lookupnext call messier.

But I think I'm still going to keep lfs3_bptr_fetch around as it
provides a nice place to deduplicate some other bits of logic:

- It makes sense to limit bptrs to compressed weights here, as opposed
  to the somewhat arbitrary lfs3_file_lookupnext function.

- And it would be a bit silly to not put the bptr's LFS3_CKFETCHES logic
  in lfs3_bptr_fetch.

  This may fetch more than previously (during crystallization pokes?),
  but better safe than sorry. LFS3_CKFETCHES will likely be a relatively
  niche feature anyways.

As for lfs3_file_traverse, I got rid of it completely.

We already have special logic in lfs3_mtree_traverse_ and lfs3_file_ck
for bptrs anyways, since bptrs, unlike data fragments, reference actual
blocks. And this disentangles lfs3_mtree_traverse_ from the file APIs,
which was a bit of an awkward design.

---

This adds a bit of code to the default build, but I think it's worth it
for the better code organization:

                     code          stack          ctx
  before:           37896           2424          636
  after:            37964 (+0.2%)   2424 (+0.0%)  636 (+0.0%)

It also saves some code in LFS3_CKFETCHES mode, thanks to deduping all
the fetch ckfetches fetch checkhes:

                     code          stack          ctx
  ckfetches before: 38144           2464          636
  ckfetches after:  38072 (-0.2%)   2472 (+0.3%)  636 (+0.0%)
This commit is contained in:
Christopher Haster
2025-06-27 18:03:13 -05:00
parent d2847f5f0e
commit 10c0a60ced
2 changed files with 151 additions and 183 deletions
+80 -50
View File
@@ -191,16 +191,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -210,12 +210,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// keep track of how many fragments we've seen
fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -331,16 +334,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -350,13 +353,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// if block crystallization is working we shouldn't be
// left with any inlined data fragments
assert(false);
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -589,16 +595,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -608,12 +614,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// keep track of how many fragments we've seen
fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -744,16 +753,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -763,13 +772,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// if block crystallization is working we shouldn't be
// left with any inlined data fragments
assert(false);
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -2064,16 +2076,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -2083,12 +2095,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// keep track of how many fragments we've seen
fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -2208,16 +2223,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -2227,12 +2242,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// keep track of how many fragments we've seen
fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -2499,16 +2517,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -2518,12 +2536,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// keep track of how many fragments we've seen
fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -2658,16 +2679,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -2677,13 +2698,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// if block crystallization is working we shouldn't be
// left with any inlined data fragments
assert(false);
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -2943,16 +2967,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -2962,12 +2986,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// keep track of how many fragments we've seen
fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,
@@ -3106,16 +3133,16 @@ code = '''
lfs3_bid_t bid;
lfs3_tag_t tag;
lfs3_bptr_t bptr;
int err = lfs3_file_traverse(&lfs3, &file, &bt,
&bid, &tag, &bptr);
lfs3_data_t data;
int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) {
break;
}
if (tag == LFS3_TAG_BRANCH) {
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer;
lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer;
printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid,
tag,
@@ -3125,13 +3152,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n",
bid,
tag,
lfs3_data_size(bptr.data));
lfs3_data_size(data));
// if block crystallization is working we shouldn't be
// left with any inlined data fragments
assert(false);
} else if (tag == LFS3_TAG_BLOCK) {
lfs3_bptr_t bptr;
lfs3_data_readbptr(&lfs3, &data,
&bptr) => 0;
printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid,
tag,