From 3f2e8b53c5e314f65eee2ce413dcbfd8a5b09cf8 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 3 Jul 2025 15:25:59 -0500 Subject: [PATCH] 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%) --- lfs3.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lfs3.c b/lfs3.c index 8a27ce3a..c0a5d45f 100644 --- a/lfs3.c +++ b/lfs3.c @@ -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;