[kvdb] Use partial GC function to reduce GC time.

This commit is contained in:
朱天龙 (Armink) 2023-03-14 22:02:11 +08:00
parent 043af70d5b
commit b34e6b52d1
1 changed files with 33 additions and 16 deletions

View File

@ -119,7 +119,14 @@ struct alloc_kv_cb_args {
uint32_t *empty_kv;
};
struct gc_cb_args {
fdb_kvdb_t db;
size_t cur_free_size;
size_t setting_free_size;
};
static void gc_collect(fdb_kvdb_t db);
static void gc_collect_by_free_size(fdb_kvdb_t db, size_t free_size);
#ifdef FDB_KV_USING_CACHE
/*
@ -980,7 +987,7 @@ __retry:
if ((empty_kv = alloc_kv(db, sector, kv_size)) == FAILED_ADDR) {
if (db->gc_request && !already_gc) {
FDB_DEBUG("Warning: Alloc an KV (size %" PRIu32 ") failed when new KV. Now will GC then retry.\n", (uint32_t)kv_size);
gc_collect(db);
gc_collect_by_free_size(db, kv_size);
already_gc = true;
goto __retry;
} else if (already_gc) {
@ -1014,7 +1021,8 @@ static bool gc_check_cb(kv_sec_info_t sector, void *arg1, void *arg2)
static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
{
struct fdb_kv kv;
fdb_kvdb_t db = arg1;
struct gc_cb_args *gc = (struct gc_cb_args *)arg1;
fdb_kvdb_t db = gc->db;
if (sector->check_ok && (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE || sector->status.dirty == FDB_SECTOR_DIRTY_GC)) {
uint8_t status_table[FDB_DIRTY_STATUS_TABLE_SIZE];
@ -1032,12 +1040,33 @@ static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
}
} while ((kv.addr.start = get_next_kv_addr(db, sector, &kv)) != FAILED_ADDR);
format_sector(db, sector->addr, SECTOR_NOT_COMBINED);
gc->cur_free_size += db_sec_size(db) - SECTOR_HDR_DATA_SIZE;
FDB_DEBUG("Collect a sector @0x%08" PRIX32 "\n", sector->addr);
if (gc->cur_free_size >= gc->setting_free_size)
return true;
}
return false;
}
static void gc_collect_by_free_size(fdb_kvdb_t db, size_t free_size)
{
struct kvdb_sec_info sector;
size_t empty_sec = 0;
struct gc_cb_args arg = {db, 0, free_size};
/* GC check the empty sector number */
sector_iterator(db, &sector, FDB_SECTOR_STORE_EMPTY, &empty_sec, NULL, gc_check_cb, false);
/* do GC collect */
FDB_DEBUG("The remain empty sector is %" PRIu32 ", GC threshold is %" PRIdLEAST16 ".\n", (uint32_t)empty_sec, FDB_GC_EMPTY_SEC_THRESHOLD);
if (empty_sec <= FDB_GC_EMPTY_SEC_THRESHOLD) {
sector_iterator(db, &sector, FDB_SECTOR_STORE_UNUSED, &arg, NULL, do_gc, false);
}
db->gc_request = false;
}
/*
* The GC will be triggered on the following scene:
* 1. alloc an KV when the flash not has enough space
@ -1045,19 +1074,7 @@ static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
*/
static void gc_collect(fdb_kvdb_t db)
{
struct kvdb_sec_info sector;
size_t empty_sec = 0;
/* GC check the empty sector number */
sector_iterator(db, &sector, FDB_SECTOR_STORE_EMPTY, &empty_sec, NULL, gc_check_cb, false);
/* do GC collect */
FDB_DEBUG("The remain empty sector is %" PRIu32 ", GC threshold is %" PRIdLEAST16 ".\n", (uint32_t)empty_sec, FDB_GC_EMPTY_SEC_THRESHOLD);
if (empty_sec <= FDB_GC_EMPTY_SEC_THRESHOLD) {
sector_iterator(db, &sector, FDB_SECTOR_STORE_UNUSED, db, NULL, do_gc, false);
}
db->gc_request = false;
gc_collect_by_free_size(db, db_max_size(db));
}
static fdb_err_t align_write(fdb_kvdb_t db, uint32_t addr, const uint32_t *buf, size_t size)
@ -1221,7 +1238,7 @@ static fdb_err_t set_kv(fdb_kvdb_t db, const char *key, const void *value_buf, s
}
/* process the GC after set KV */
if (db->gc_request) {
gc_collect(db);
gc_collect_by_free_size(db, KV_HDR_DATA_SIZE + FDB_WG_ALIGN(strlen(key)) + FDB_WG_ALIGN(buf_len));
}
}