Skip to content

Support explicitly call GC during idle times on SPIFFS #2870

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

Closed
joelucid opened this issue Jan 16, 2017 · 5 comments
Closed

Support explicitly call GC during idle times on SPIFFS #2870

joelucid opened this issue Jan 16, 2017 · 5 comments
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.

Comments

@joelucid
Copy link
Contributor

SPIFFS writes get very slow when there are no free blocks available. Therefore it makes sense to clear blocks in the background when the application is idle. The following patch exposes a gc() call which in turn calls SPIFFS_gc_quick which serves exactly this purpose.

diff --git a/cores/esp8266/FS.cpp b/cores/esp8266/FS.cpp
index 6ae11e1..6bd359c 100644
--- a/cores/esp8266/FS.cpp
+++ b/cores/esp8266/FS.cpp
@@ -173,6 +173,13 @@ void FS::end() {
}
}

+bool FS::gc() {

  • if (!_impl) {
  •    return false;
    
  • }
  • return _impl->gc();
    +}

bool FS::format() {
if (!_impl) {
return false;
diff --git a/cores/esp8266/FS.h b/cores/esp8266/FS.h
index 79620f9..ce42ccf 100644
--- a/cores/esp8266/FS.h
+++ b/cores/esp8266/FS.h
@@ -125,6 +125,7 @@ public:
bool rename(const char* pathFrom, const char* pathTo);
bool rename(const String& pathFrom, const String& pathTo);

  • bool gc();
    protected:
    FSImplPtr _impl;
    };
    diff --git a/cores/esp8266/FSImpl.h b/cores/esp8266/FSImpl.h
    index e5694b5..242811c 100644
    --- a/cores/esp8266/FSImpl.h
    +++ b/cores/esp8266/FSImpl.h
    @@ -71,6 +71,8 @@ public:
    virtual DirImplPtr openDir(const char* path) = 0;
    virtual bool rename(const char* pathFrom, const char* pathTo) = 0;
    virtual bool remove(const char* path) = 0;
  • virtual bool gc() = 0;

};

#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPIFFS)
diff --git a/cores/esp8266/spiffs_api.h b/cores/esp8266/spiffs_api.h
index f98df11..f42e43e 100644
--- a/cores/esp8266/spiffs_api.h
+++ b/cores/esp8266/spiffs_api.h
@@ -165,6 +165,12 @@ public:
return true;
}

  • bool gc() override {
  •   return SPIFFS_gc_quick( &_fs, 0 ) == SPIFFS_OK;
    
  • }
@devyte
Copy link
Collaborator

devyte commented Oct 4, 2017

@joelucid this looks interesting. Care to make a PR?

@devyte devyte added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Oct 4, 2017
@TD-er
Copy link
Contributor

TD-er commented Apr 1, 2019

What is the status of the internal garbage collector right now?
I've only seen it used when there is some hardly any space left.

// Find free object lookup entry
// Iterate over object lookup pages in each block until a free object id entry is found
s32_t spiffs_obj_lu_find_free(
spiffs *fs,
spiffs_block_ix starting_block,
int starting_lu_entry,
spiffs_block_ix *block_ix,
int *lu_entry) {
s32_t res;
if (!fs->cleaning && fs->free_blocks < 2) {
res = spiffs_gc_quick(fs, 0);
if (res == SPIFFS_ERR_NO_DELETED_BLOCKS) {
res = SPIFFS_OK;
}
SPIFFS_CHECK_RES(res);
if (fs->free_blocks < 2) {
return SPIFFS_ERR_FULL;
}
}
res = spiffs_obj_lu_find_id(fs, starting_block, starting_lu_entry,

Is there a better way to help improve SPIFFS performance? Or is this currently the best way to do it?
If so, then I can make a PR for it, since it looks like a good command to have and perhaps call it when deleting a (large) file.

@devyte
Copy link
Collaborator

devyte commented Apr 2, 2019

No work has been on this front. As you said, this applies in the case where there is little space left, hence the smaller SPIFFS sizes.

@TD-er
Copy link
Contributor

TD-er commented Apr 3, 2019

It looks to me, this spiffs_gc_quick is only called from within the write block.
But this garbage collection cannot do garbage collection when there are open file descriptor handles with something other than read-only.
So this means it is not really cleaning when writing.

This does make it even more useful for a separate GC function to be called.
Also it would make sense to call it ourselves right after mounting the file system and before opening any file, and in tasks where files are to be written.

I will create a PR with the changes suggested in the opening post.

@earlephilhower
Copy link
Collaborator

Closed with #5944

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.
Projects
None yet
Development

No branches or pull requests

4 participants