-
Notifications
You must be signed in to change notification settings - Fork 816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Too inefficient way to append file content, when i need to save file immediately #862
Comments
Create a file for each data and name it with a number as the suffix.But this will make the entire logic more complex and create a large number of files, it is unknown whether this will significantly reduce the performance of the file system. Although I am more concerned about data validity and space utilization efficiency compared to performance, low file system performance may lead to watchdog restarts. |
It has to be said that there is still room for optimization of the LFS system's strategy for large files. In fact, files without sync or close are not saved to flash. Even if 16KB of data has been written, in my example, it means 4block because it exceeds the cache and has been written to flash. However, if there is no sync or close, the data cannot be successfully read. So if you want to store and read data that can be accessed at any time in flash, you must perform a sync or close operation after each write. However, LFS's write strategy for large files is frustrating. Even if I add 1 Byte of content to this outline file, LFS will erase a new sector and then copy the contents of this 1 Byte and the previous content. For example, if a file now has 4096+512Byte, the entire file takes up 2Block, 1 block 4096 data; 2 block 512 data 32 index. Obviously, there are still 3552B unused in block 2. If I add 1 byte of data at this time, lfs will erase a new block to store the updated data. Delete 2 block, move to 3 block At this time, 1 block 4096 data; 3Block 513data 32 index. This clearly wastes a large amount of the remaining space of the 2block, which is nearly 7 times the space used. It is difficult to imagine the rationality of this approach. It is worth noting that if 1B more data is added, lfs will also repeat the above operation! This waste of space confuses me. |
Additionally, I noticed that updating the inline file is more reasonable and utilizes space more effectively. Can several inline files be used to maintain a large outline file without changing the source code? In short, the current outline file scheme is not a reasonable one |
Hi @muguou, thanks for creating an issue, the feedback and ideas are useful. This is a long-term issue I am currently working on, along with a number of other file data-structure changes, though it will take some time to implement and test. I think I've more or less arrived at the same conclusion you have, that is, inlined data can be utilized better. Though any inlined data has an inherent 4x storage overhead, so there is a bit of a tradeoff. The current plan, susceptible to change:
In theory, these combined should eliminate the issues with syncing files. As long as inline data is larger than the program size, writes can go into the file's inlined data until program aligned. So we should be able to avoid block rewrites even when repeatedly syncing.
Currently file lookup is a Though it may still be more efficient thank one large file with the current implementation, depending on cost of rewriting the last block in a file. |
I am a bit confused reading this issue, but can see the same behavior on my system. |
@Olstyle, that's easy to answer. I'm not perfect and littlefs (any filesystem really) is a complex system. The intention is for append to be the most efficient solution, and after the planned changes in #862 (comment) (though this will take some time), it should return to being the most efficient solution for logging. I'd also be hesitant to suggest the above many-files solution as always better than append. It's a workaround for current design issues that may have unpredicted side-effects. For 1. lookup cost in directories is currently Append is also still the most efficient solution if you don't need to sync, though I realize that's not a good idea for logging. Streaming sensor data however... |
How is a changed block handled now? It seems a new block is allocated and then all old data is copied with new data applied over the affected bytes. Then all later blocks are copied to new blocks to allow references to be updated? |
Hi @kyrreaa, the answer is your first description. littlefs creates a copy of any blocks being modified, and then updates any dependent blocks so references are up to date. Modifying the affected block is not an acceptable strategy here. Wear-leveling aside, it breaks power-loss resilience, as a power-loss could leave us in a state where the block is only partially written and metadata is not up to date. You're right it would be faster though! Which is why littlefs will probably always be less-performant than non-power-loss-resilient filesystems. |
Hi guys,
After frustration tests trying to create 200 logs files with the suffix and delete the oldest files( The performance decreased linearly), I decided to overwrite the oldest files and maintain the same files names log1.txt ... log200.txt (circular buffer index to know the oldest and newest). I figured out a constant performance in this approach, no more increasing over the time and random open/close times. I did some tests creating folders and puts the files inside. I could see a better performance ( Folder 1 -> log1, ..., log20, Folder 2 -> log21, ..., log40 ...) than 200 files in the root filesystem. Below is the difference between using folders(10 folders to store 200logs) and putting the same files in the root directory. In this case, I could see a huge difference in the metadata compact spikes. I also set the parameter:
To reduce the spikes and have an acceptable performance for my application. I think this confirm what @geky said:
I think for this LFS algorithm logic, as less files do you have, better the performance. I didn't try big files yet. But for small one, looks better breaks it in folders when its possible. I hope this can help someone else that are having performances issues with small log files. |
I use W25Q128 Flash.
My LFS adopts the following configuration.
I have some data that needs to be stored in flash at any time when there is a power outage. So every time I use lfs to open a file (use open type writeOnly, append) and write to it, I immediately close the file (I also used sync testing, and the results were the same).
If I don't close file it or synchronize, then the power outage data will be lost at this time
The data is stored in a structure with a size of 64B, and the size is always 64 when writing. Because it immediately shuts down after each write, lfs saves the data back to flash after each write. In this case, when the file size is over 512 B, every time I save data, lfs erases a new sector. You know, I only wrote 64B of data, but every time lfs erases an entire sector of 4096B, there is a difference of 2 ^ 6=64 times. This is a bit too inefficient, and even less efficient than simply erasing the sectors in place.
Is it caused by my usage error.
My log is as follows。
The
"i" mean times of write.
"size" means the total number of bytes in the file now( befor write data and close file ).
"fe" means erase sector .
Is it my usage mistake, or is it how lfs is designed.
The text was updated successfully, but these errors were encountered: