Manually inlined lfs3_file_crystallize into lfs3_file_flush_

This was the main culprit behind our stack increase. Inlining
lfs3_file_crystallize into lfs3_file_flush_ adds a bit of code, but as a
tradeoff:

- Keeps all lfs3_file_crystallization_ calls at the same abstraction
  level, which is generally easier to reason about and avoids issues
  with things like lfs3_alloc_ckpoints.

- Makes some low-level interactions, such as LFS3_o_UNCRYST masking,
  more obvious.

- Reduces the stack hot-path by the cost of lfs3_file_flush_

Saves some stack at a code cost:

               code          stack          ctx
  before:     37492           2464          656
  after:      37504 (+0.0%)   2448 (-0.6%)  656 (+0.0%)

Now that the dust has settled a bit, we can also compare the lazy
grafting vs lazy crystallization builds:

               code          stack          ctx
  lazy-graft: 38020           2456          656
  lazycryst:  37504 (-1.4%)   2448 (-0.3%)  656 (+0.0%)
This commit is contained in:
Christopher Haster
2025-07-03 15:25:59 -05:00
parent 35e407372c
commit 3f2e8b53c5

20
lfs3.c
View File

@@ -13095,9 +13095,17 @@ static int lfs3_file_flush_(lfs3_t *lfs3, lfs3_file_t *file,
// if we're mid-crystallization, finish crystallizing the block
// and graft it into our bshrub/btree
int err = lfs3_file_crystallize(lfs3, file);
if (err) {
return err;
if (lfs3_o_isuncryst(file->b.o.flags)) {
// finish crystallizing
int err = lfs3_file_crystallize_(lfs3, file,
file->leaf.pos - lfs3_bptr_off(&file->leaf.bptr), -1, -1,
0, NULL, 0);
if (err) {
return err;
}
// we should have crystallized
LFS3_ASSERT(!lfs3_o_isuncryst(file->b.o.flags));
}
// before we can crystallize we need to figure out the best
@@ -13138,7 +13146,7 @@ static int lfs3_file_flush_(lfs3_t *lfs3, lfs3_file_t *file,
// start crystallizing!
//
// lfs3_file_crystallize_ handles block allocation/relocation
err = lfs3_file_crystallize_(lfs3, file,
int err = lfs3_file_crystallize_(lfs3, file,
crystal_start, -1, crystal_end - crystal_start,
pos, buffer, size);
if (err) {
@@ -13451,6 +13459,8 @@ int lfs3_file_flush(lfs3_t *lfs3, lfs3_file_t *file) {
}
// unflushed files must be unsynced
LFS3_ASSERT(lfs3_o_isunsync(file->b.o.flags));
// uncrystallized files must be unsynced
LFS3_ASSERT(lfs3_o_isunsync(file->b.o.flags));
// unflushed files can't be readonly
LFS3_ASSERT(!lfs3_o_isrdonly(file->b.o.flags));
@@ -13479,8 +13489,8 @@ int lfs3_file_flush(lfs3_t *lfs3, lfs3_file_t *file) {
file->b.o.flags &= ~LFS3_o_UNFLUSH;
}
// and crystallize/graft our leaf
#if !defined(LFS3_KVONLY) && !defined(LFS3_2BONLY)
// and crystallize/graft our leaf
err = lfs3_file_crystallize(lfs3, file);
if (err) {
goto failed;