Skip to content
Pavel Melnikov edited this page Dec 22, 2017 · 13 revisions

Mail me or post an issue on github if you want answers here.

Why is spiffs so slow?

Apart from the underlying hardware (CPU and SPI flash), it is mainly because spiffs uses little memory. Spiffs does not build any file-trees in ram or such, it is really more of a brute-force file system. One may enable caches and stuff, but it will probably still be pretty slow. The slowest part of spiffs is the file system integrity check, SPIFFS_check. This is because checking must cross-reference huge parts of information using just a handful of bytes. Hence, it runs several scans over the full file system. That said, a lot of effort has been put into optimizing spiffs, it should not be slower than it must be.

How does spiffs handle powerlosses?

There is a scheme for updating data: when modifying a page the old page is first marked as being modified, then the new page is written with the updated (and possibly not updated) data. Then the old page is removed, and finally the new page is marked as finalized. In event of a power loss somewhere, there might be two pages with same id, but the status of these pages will indicate which one is valid. There also are certain integrity tests that always are tested when accessing files. If the problem can be mended, there will be an attempt to do this if possible. In the early days of spiffs, a full integrity check was made at mount time, but I removed this as it took so long time. It must now be invoked by user. This integrity check will remove such duplicate pages mentioned before and try to fix a bunch of other problems that might arise from power losses.

Powerlosses cont'd: When should I run SPIFFS_check?

The check mends broken files, cleans away unreferenced pages, and so on. In the beginning spiffs ran this on mount. However, on larger flashes this became too slow - thus, the check was put in its own function.

So when to run it? If SPIFFS_info returns used > total Also, getting any of the error codes SPIFFS_ERR_NOT_FINALIZED, SPIFFS_ERR_NOT_INDEX, SPIFFS_ERR_IS_INDEX, SPIFFS_ERR_IS_FREE, SPIFFS_ERR_INDEX_SPAN_MISMATCH, SPIFFS_ERR_DATA_SPAN_MISMATCH, SPIFFS_ERR_INDEX_REF_FREE, SPIFFS_ERR_INDEX_REF_LU, SPIFFS_ERR_INDEX_REF_INVALID, SPIFFS_ERR_INDEX_FREE, SPIFFS_ERR_INDEX_LU, SPIFFS_ERR_INDEX_INVALID.

If a powerloss can be detected on startup it is of course of great input to decide whether to run check or not. Some CPUs have batterybacked RAM which can be used to detect if spiffs was running when power broke. One could for instance set a batterybacked bit in the macro SPIFFS_LOCK and clear it in SPIFFS_UNLOCK. On startup, if powerloss is detected, and if this bit is set, we run check.

Also, as maintenance a check should/could run at least once during a year/month/week or whatever. Then again, it may not be necessary at all - it is up to you, the power, and the app itself.

On battery powered systems I'd recommend running it during charging and iff battery level is above some certain level. The check can of course handle a powerloss also, but if finding any of the errors above the fs is inconsistent in some way.

As a side note I had an idea of reserving one special parity page in the fs where one bit is cleared when starting some spiffs operation, and clearing another bit when operation ends. On mount, and if the number of cleared bits are uneven, a check should run. As I had batterybacked ram, I never needed this. But if someone feel a great need of such a check-if-I-should-run-check feature, file an issue and start bugging me - it might still happen :)

How does the cache work?

If build time configuration SPIFFS_CACHE is enabled, spiffs will keep mirrors of the flash in ram used when reading stuff. If build time configuration SPIFFS_CACHE_WR is disabled, all writes are write through. If SPIFFS_CACHE_WR is enabled, also writes are cached. The write cache (if there is one) for a file is flushed when calling SPIFFS_fflush, SPIFFS_close, SPIFFS_read, SPIFFS_fstat, SPIFFS_lseek. All files are flushed when calling SPIFFS_unmount. This means that e.g. SPIFFS_read might give errors concerning write operations.

Can spiffs run on an i2c eeprom?

Nope. At least none of the i2c eeproms I've come across. Spiffs uses the nor flash way of writing extensively, where a written byte is sort of AND-written. E.g. say you have a byte on your flash being erased, i.e. is 0xFF. If you first write 0xFE and then 0x7F to this same byte, spiffs expects this byte to be read as 0x7E. Of course, one could write a hal for spiffs that first reads what is supposed to be written, then AND writes in memory, and finally stores this ANDed data to the i2c eeprom. Considering i2c bus speeds, the performance would be horrible.

Why does half the tests fail when running make test?

Because of a missing folder. Run make all first.

How long will my SPI flash live?

That depends on everything. But, let's construct a simple case where we do not dive into details too much.

Let's say we have a 1MB flash. There is only one file. Each second we open the file, read a number, increment it, and store the file again.

Suppose we divide the flash into 128 bytes pages and 64k blocks. The flash copes with 10000 erases before it fails.

Thus, we will have 1MB / 64k = 16 blocks. Each block has 512 pages, and one file update will consume two pages (metadata + data), meaning we can do 512/2 = 256 file updates before we've used a full block which needs erasing before reuse. Also, spiffs always need two free blocks.

Considering above, after (16-2) * 256 = 3584 file updates the system is full of deleted pages and blocks will need to be erased. Henceforth, after each 256th file update a block must be erased. As we have 16 blocks and have wear leveling, it will take 256 * 16 file updates before same block is erased again. This we can do 10000 times before things fail, so to sum it up we can do 3584 + (256 * 16) * 10000 file updates before the spi flash is worn out, roughly 40960000 times. To play it safe as we haven't considered some extra meta data, we multiply by 0.75 (pretty aggressive) we sum it up to 30,7 million.

Which at one write per second is 355 days.

On the other hand, if your update occurs once per minute you can expect a failure in 58 years.

Also, many flashes today can be erased 100000 times (or more) before failure which would multiply above life time by ten. Check the datasheet.

Will file list order be preserved?

No. When you list files on your file system, the order is arbitrary. Also, due to garbage collection, it may be rescrambled as soon as you make any changes to your file system. If ordering of files are important it is up to the user to take care of this; e.g. by a sequence number in the file name.