Littlefs: read access slowing down boot after boot

Created on 27 May 2020  路  6Comments  路  Source: littlefs-project/littlefs

Hi,
I noticed a strange behaviour that may be normal but I want to be sure.

I run the following code:

  • example code (boot count) : so read + write access
  • benchmark uC cycles start
  • file read of another file not invloved in boot count
  • benchmark uC cycles stop

My initial intention was to optimize the file read (I implemented a fgets() function, and I wanted to compare a byte by byte implementation to a buffered implementation).
I noticed that my processor cycles count is always incrementing boot after boot (~ 6000 cycles more each time). If I remove the example code, my processor cycles count is stable after each boot.

I understand that the writes change the file system, so that can change the speed of some operation and behaviour of garbage collection.
But is it normal that the speed of reading a file that has not been touched changes ? And will it stop changing one day ?

performance

All 6 comments

Confirm. I have met the same issue.

@blomnik and @PoppaChubby,

What flags are you using when you open the boot count file? If you open the file as read/write the file system will always commit a new version of the file which could result in compaction.

I recommend opening the file as read only if you don't intend on altering the file content.

If this does not solve your problem, can I ask what version your are currently experiencing this issue on?

Hi, sorry about the late response. This sounds like the files are sharing a metadata pair.

In littlefs, each file's data is stored in a skip-list of blocks. These lists are independent, so a write to one file doesn't affect the other file. But this isn't true for the _metadata_ of a file (the file type, it's length, the pointer to the skip-list).

In littlefs a file's metadata is stored in metadata pairs. These are 2-block logs that provide atomic updates by crcing new metadata which is appended instead of overwritten. But giving each file its own metadata pair turns out to be rather expensive, especially for small files, so instead multiple files in the same directory have their metadata placed in the same metadata pair.

One of the current issues right now (performance wise) with littlefs is that these metadata logs need to be scanned to find the most recent piece of metadata. This starts off cheap when the metadata logs are first initialized, but as the metadata logs fill with updates this scanning cost grows until the metadata pair is full and metadata compaction (in-log garbage collection) kicks in.

And, as a side-effect of files sharing metadata pairs, writes to one file can cause a shared metadata pair to fill with updates.


Another interesting thing is that metadata pairs in littlefs are closely tied to directories. Directories are just linked-lists of metadata pairs which get scanned for filenames when you open a file (the filename is just another piece of metadata).

This means you could store the two files in different directories to force independent metadata pairs.

lfs_file_open(&lfs, &file, "/readonly_files/readonly_file_here.txt", LFS_O_RDONLY);
lfs_file_open(&lfs, &file, "/writeable_files/writable_file_here.txt", LFS_O_RDWR);

Not necessarily the nicest solution, but it is an option.

Hello, everybody.
@thrasher8390 , if you will look at the 'boot_count' example in README.md file, you'll get an answer for your post: it is impossible to open this file for read only. :)

@geky, I guess it is a source of performance degradation. Thank you for your response. Unfortantly, I can't split READONLY and READWRITE modes for 'boot_count' file due to obvious reasons. :) But in all other cases, it useful to know this "trick". I guess, this design was described in DESIGN.md, but it is not obvious that metadata (is it tags?) grows until GC compact it.

Yeah, the "tags" are pieces of metadata written to the log. The theory is that the growth of the metadata is bounded to one erase block, so it doesn't grow indefinitely unlike in true logging filesystems. But with large erase blocks it becomes significant.

At some point I should go through and add some illustrative examples of how littlefs's internals work. But that may have to come after taking care of the other issues.

Hi everybody,
thanks for the explanations.
Yes, indeed the processor load stops incrementing after some time. I noticed that a few days after having posted my question, but forgot to post an update, sorry for that...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

roceh picture roceh  路  8Comments

gofortime picture gofortime  路  5Comments

roceh picture roceh  路  6Comments

nizhq picture nizhq  路  3Comments

umanayana picture umanayana  路  5Comments