Settings: NVS: Add cache for nvs name lookup

Add cache for name id lookup.

Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
This commit is contained in:
Lingao Meng 2022-10-26 16:01:07 +08:00 committed by Carles Cufí
commit 9cb1ff7fce
3 changed files with 110 additions and 17 deletions

View file

@ -63,6 +63,24 @@ config SETTINGS_NVS
help
Enables NVS storage support
if SETTINGS_NVS
config SETTINGS_NVS_NAME_CACHE
bool "NVS name lookup cache"
help
Enable NVS name lookup cache, used to reduce the Settings name
lookup time.
config SETTINGS_NVS_NAME_CACHE_SIZE
int "NVS name lookup cache size"
default 128
range 1 65535
depends on SETTINGS_NVS_NAME_CACHE
help
Number of entries in Settings NVS name cache.
endif # SETTINGS_NVS
config SETTINGS_CUSTOM
bool "CUSTOM"
help

View file

@ -38,6 +38,14 @@ struct settings_nvs {
struct nvs_fs cf_nvs;
uint16_t last_name_id;
const struct device *flash_dev;
#if CONFIG_SETTINGS_NVS_NAME_CACHE
struct {
uint16_t name_hash;
uint16_t name_id;
} cache[CONFIG_SETTINGS_NVS_NAME_CACHE_SIZE];
uint16_t cache_next;
#endif
};
/* register nvs to be a source of settings */

View file

@ -10,6 +10,7 @@
#include <zephyr/settings/settings.h>
#include "settings/settings_nvs.h"
#include <zephyr/sys/crc.h>
#include "settings_priv.h"
#include <zephyr/storage/flash_map.h>
@ -72,6 +73,51 @@ int settings_nvs_dst(struct settings_nvs *cf)
return 0;
}
#if CONFIG_SETTINGS_NVS_NAME_CACHE
static void settings_nvs_cache_add(struct settings_nvs *cf, const char *name,
uint16_t name_id)
{
uint16_t name_hash = crc16_ccitt(0xffff, name, strlen(name));
cf->cache[cf->cache_next].name_hash = name_hash;
cf->cache[cf->cache_next++].name_id = name_id;
cf->cache_next %= CONFIG_SETTINGS_NVS_NAME_CACHE_SIZE;
}
static uint16_t settings_nvs_cache_match(struct settings_nvs *cf, const char *name,
char *rdname, size_t len)
{
uint16_t name_hash = crc16_ccitt(0xffff, name, strlen(name));
int rc;
for (int i = 0; i < CONFIG_SETTINGS_NVS_NAME_CACHE_SIZE; i++) {
if (cf->cache[i].name_hash != name_hash) {
continue;
}
if (cf->cache[i].name_id <= NVS_NAMECNT_ID) {
continue;
}
rc = nvs_read(&cf->cf_nvs, cf->cache[i].name_id, rdname, len);
if (rc < 0) {
continue;
}
rdname[rc] = '\0';
if (strcmp(name, rdname)) {
continue;
}
return cf->cache[i].name_id;
}
return NVS_NAMECNT_ID;
}
#endif /* CONFIG_SETTINGS_NVS_NAME_CACHE */
static int settings_nvs_load(struct settings_store *cs,
const struct settings_load_arg *arg)
{
@ -125,6 +171,10 @@ static int settings_nvs_load(struct settings_store *cs,
read_fn_arg.fs = &cf->cf_nvs;
read_fn_arg.id = name_id + NVS_NAME_ID_OFFSET;
#if CONFIG_SETTINGS_NVS_NAME_CACHE
settings_nvs_cache_add(cf, name, name_id);
#endif
ret = settings_call_set_handler(
name, rc2,
settings_nvs_read_fn, &read_fn_arg,
@ -152,6 +202,15 @@ static int settings_nvs_save(struct settings_store *cs, const char *name,
/* Find out if we are doing a delete */
delete = ((value == NULL) || (val_len == 0));
#if CONFIG_SETTINGS_NVS_NAME_CACHE
name_id = settings_nvs_cache_match(cf, name, rdname, sizeof(rdname));
if (name_id != NVS_NAMECNT_ID) {
write_name_id = name_id;
write_name = false;
goto found;
}
#endif
name_id = cf->last_name_id + 1;
write_name_id = cf->last_name_id + 1;
write_name = true;
@ -178,7 +237,24 @@ static int settings_nvs_save(struct settings_store *cs, const char *name,
continue;
}
if ((delete) && (name_id == cf->last_name_id)) {
if (!delete) {
#if CONFIG_SETTINGS_NVS_NAME_CACHE
settings_nvs_cache_add(cf, name, name_id);
#endif
write_name_id = name_id;
write_name = false;
}
goto found;
}
found:
if (delete) {
if (name_id == NVS_NAMECNT_ID) {
return 0;
}
if (name_id == cf->last_name_id) {
cf->last_name_id--;
rc = nvs_write(&cf->cf_nvs, NVS_NAMECNT_ID,
&cf->last_name_id, sizeof(uint16_t));
@ -190,26 +266,17 @@ static int settings_nvs_save(struct settings_store *cs, const char *name,
}
}
if (delete) {
rc = nvs_delete(&cf->cf_nvs, name_id);
rc = nvs_delete(&cf->cf_nvs, name_id);
if (rc >= 0) {
rc = nvs_delete(&cf->cf_nvs, name_id +
if (rc >= 0) {
rc = nvs_delete(&cf->cf_nvs, name_id +
NVS_NAME_ID_OFFSET);
}
if (rc < 0) {
return rc;
}
return 0;
}
write_name_id = name_id;
write_name = false;
break;
}
if (delete) {
if (rc < 0) {
return rc;
}
return 0;
}