Skip to content

Commit 42c2768

Browse files
committed
settings: zms: add a cache for hash collisions
adding a lookup cache for hash collisions improves write speed as it doesn't look for the name in the storage if no hash collision exists Signed-off-by: Riadh Ghaddab <[email protected]>
1 parent 7c32f11 commit 42c2768

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

subsys/settings/Kconfig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,25 @@ config SETTINGS_ZMS
4747
help
4848
Use ZMS as settings storage backend.
4949

50+
if SETTINGS_ZMS
51+
52+
config SETTINGS_ZMS_NAME_CACHE
53+
bool "ZMS name lookup cache"
54+
select SYS_HASH_FUNC32
55+
help
56+
Enable ZMS lookup cache, used to reduce the Settings name
57+
lookup time by checking if its hash had a collision.
58+
59+
config SETTINGS_ZMS_NAME_CACHE_SIZE
60+
int "ZMS name lookup cache size"
61+
default 128
62+
range 1 $(UINT32_MAX)
63+
depends on SETTINGS_ZMS_NAME_CACHE
64+
help
65+
Number of entries in Settings ZMS name cache.
66+
67+
endif # SETTINGS_ZMS
68+
5069
config SETTINGS_FCB
5170
bool "FCB"
5271
depends on FCB

subsys/settings/include/settings/settings_zms.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ struct settings_zms {
7171
struct settings_store cf_store;
7272
struct zms_fs cf_zms;
7373
const struct device *flash_dev;
74+
#if CONFIG_SETTINGS_ZMS_NAME_CACHE
75+
struct {
76+
uint32_t name_hash;
77+
bool has_collision;
78+
} cache[CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE];
79+
80+
uint32_t cache_next;
81+
#endif
7482
uint32_t last_hash_id;
7583
uint32_t second_to_last_hash_id;
7684
uint8_t hash_collision_num;

subsys/settings/src/settings_zms.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,41 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
146146
return rc;
147147
}
148148

149+
#if CONFIG_SETTINGS_ZMS_NAME_CACHE
150+
static void settings_zms_cache_add(struct settings_zms *cf, uint32_t name_hash, bool has_collision)
151+
{
152+
cf->cache[cf->cache_next].name_hash = name_hash;
153+
cf->cache[cf->cache_next++].has_collision = has_collision;
154+
155+
cf->cache_next %= CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE;
156+
}
157+
158+
static bool settings_zms_cache_match(struct settings_zms *cf, uint32_t name_hash)
159+
{
160+
int cache_index;
161+
162+
if (!cf->cache_next) {
163+
cache_index = CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE - 1;
164+
} else {
165+
cache_index = cf->cache_next - 1;
166+
}
167+
168+
for (int i = 0; i < CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE; i++) {
169+
/* we check cache from recent values to old values */
170+
if (cf->cache[cache_index--].name_hash != name_hash) {
171+
if (cache_index < 0) {
172+
cache_index = CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE - 1;
173+
}
174+
continue;
175+
}
176+
177+
return !cf->cache[i].has_collision;
178+
}
179+
180+
return false;
181+
}
182+
#endif /* CONFIG_SETTINGS_ZMS_NAME_CACHE */
183+
149184
static int settings_zms_load(struct settings_store *cs, const struct settings_load_arg *arg)
150185
{
151186
int ret = 0;
@@ -199,6 +234,11 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
199234
break;
200235
}
201236

237+
#if CONFIG_SETTINGS_ZMS_NAME_CACHE
238+
settings_zms_cache_add(cf, ll_hash_id & ZMS_HASH_MASK,
239+
ZMS_COLLISION_NUM(ll_hash_id) > 0);
240+
#endif
241+
202242
/* update next ll_hash_id */
203243
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
204244
sizeof(struct settings_hash_linked_list));
@@ -236,6 +276,17 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
236276
/* MSB is always 1 */
237277
name_hash |= BIT(31);
238278

279+
#if CONFIG_SETTINGS_ZMS_NAME_CACHE
280+
bool name_in_cache = false;
281+
282+
name_in_cache = settings_zms_cache_match(cf, name_hash & ZMS_HASH_MASK);
283+
if (name_in_cache) {
284+
write_name = false;
285+
hash_collision = false;
286+
goto no_hash_collision;
287+
}
288+
#endif
289+
239290
/* Let's find out if there is no hash collisions in the storage */
240291
write_name = true;
241292
hash_collision = true;
@@ -342,6 +393,13 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
342393
cf->last_hash_id = name_hash | 1;
343394
}
344395

396+
#if CONFIG_SETTINGS_ZMS_NAME_CACHE
397+
if (!name_in_cache) {
398+
settings_zms_cache_add(cf, name_hash & ZMS_HASH_MASK,
399+
ZMS_COLLISION_NUM(name_hash) > 0);
400+
}
401+
#endif
402+
345403
return 0;
346404
}
347405

0 commit comments

Comments
 (0)