From 9cb1ff7fcee23928d89fda9ee23d64b6cb4a54f2 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Wed, 26 Oct 2022 16:01:07 +0800 Subject: [PATCH] Settings: NVS: Add cache for nvs name lookup Add cache for name id lookup. Signed-off-by: Lingao Meng --- subsys/settings/Kconfig | 18 ++++ .../settings/include/settings/settings_nvs.h | 8 ++ subsys/settings/src/settings_nvs.c | 101 +++++++++++++++--- 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/subsys/settings/Kconfig b/subsys/settings/Kconfig index 97945714641..da9d27b9555 100644 --- a/subsys/settings/Kconfig +++ b/subsys/settings/Kconfig @@ -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 diff --git a/subsys/settings/include/settings/settings_nvs.h b/subsys/settings/include/settings/settings_nvs.h index 6fe61677e5f..ce34e192c24 100644 --- a/subsys/settings/include/settings/settings_nvs.h +++ b/subsys/settings/include/settings/settings_nvs.h @@ -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 */ diff --git a/subsys/settings/src/settings_nvs.c b/subsys/settings/src/settings_nvs.c index 758fd0fb8ab..ecbc8a0d2a6 100644 --- a/subsys/settings/src/settings_nvs.c +++ b/subsys/settings/src/settings_nvs.c @@ -10,6 +10,7 @@ #include #include "settings/settings_nvs.h" +#include #include "settings_priv.h" #include @@ -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; }