forked from Imagelibrary/littlefs
Reworked crystallization to better use erased-state on rewrites
This adopts lazy crystallization in _addition_ to lazy grafting, managed
by separate LFS_o_UNCRYST and LFS_o_UNGRAFT flags:
LFS_o_UNCRYST 0x00400000 File's leaf not fully crystallized
LFS_o_UNGRAFT 0x00800000 File's leaf does not match bshrub/btree
This lets us graft not-fully-crystallized blocks into the tree without
needing to fully crystallize, avoiding repeated recrystallizations when
linearly rewriting a file.
Long story short, this gives file rewrites roughly the same performance
as linear file writes.
---
In theory you could also have fully crystallized but ungrafted blocks
(UNGRAFT + ~UNCRYST), but this doesn't happen with the current logic.
lfsr_file_crystallize eagerly grafts blocks once they're crystallized.
Internally, lfsr_file_crystallize replaces lfsr_file_graft for the
"don't care, gimme file->leaf" operation. This is analogous to
lfsr_file_flush for file->cache.
Note we do _not_ use LFS_o_UNCRYST to track erased-state! If we did,
erased-state wouldn't survive lfsr_file_flush!
---
Of course, this adds even more code. Fortunately not _that_ much
considering how many lines of code changed:
code stack ctx
before: 37012 2304 636
after 37084 (+0.2%) 2304 (+0.0%) 636 (+0.0%)
There is another downside however, and that's that our benchmarked disk
usage is slightly worse during random writes.
I haven't fully investigated this, but I think it's due to more
temporary fragments/blocks in the B-tree before flushing. This can cause
B-tree inner nodes to split earlier than when eagerly recrystallizing.
This also leads to higher disk usage pre-flush since we keep both the
old and new blocks around while uncrystallized, but since most rewrites
are probably going to be CoW on top of committed files, I don't think
this will be a big deal.
Note the disk usage ends up the same after lfsr_file_flush.
This commit is contained in:
@@ -44,7 +44,8 @@ FLAGS = [
|
||||
('^', 'ORPHAN', 0x50000000, "Type = orphan" ),
|
||||
('^', 'TRAVERSAL', 0x60000000, "Type = traversal" ),
|
||||
('^', 'UNKNOWN', 0x70000000, "Type = unknown" ),
|
||||
('o', 'UNGRAFT', 0x00800000, "File's leaf does not match btree" ),
|
||||
('o', 'UNCRYST', 0x00400000, "File's leaf not fully crystallized" ),
|
||||
('o', 'UNGRAFT', 0x00800000, "File's leaf does not match bshrub/btree" ),
|
||||
('o', 'UNFLUSH', 0x01000000, "File's data does not match disk" ),
|
||||
('o', 'UNSYNC', 0x02000000, "File's metadata does not match disk" ),
|
||||
('o', 'UNCREAT', 0x04000000, "File does not exist yet" ),
|
||||
|
||||
Reference in New Issue
Block a user