Skip to content

Commit 3679afc

Browse files
committed
[nrf fromlist] settings: zms: add cache for linked list hash
Increase the load performance by adding an optional cache for the linked list hashes. This is used only when the settings_load is called with NULL parameter and we need to load all Settings that exist in the persistent storage. Cache is enabled using SETTINGS_ZMS_LL_CACHE and the size of the cache is set using SETTINGS_ZMS_LL_CACHE_SIZE. Each cache entry will add 8 bytes of RAM usage. Upstream PR #: 87792 Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit a874e07e6d4035d1d0c3f92f29406e39d5faa37d)
1 parent 52ad406 commit 3679afc

File tree

3 files changed

+91
-15
lines changed

3 files changed

+91
-15
lines changed

subsys/settings/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ config SETTINGS_ZMS_NAME_CACHE_SIZE
6464
help
6565
Number of entries in Settings ZMS name cache.
6666

67+
config SETTINGS_ZMS_LL_CACHE
68+
bool "ZMS linked list lookup cache"
69+
help
70+
Enable ZMS lookup cache for linked list, used to reduce the
71+
Settings load time by having most linked list elements already
72+
in cache.
73+
74+
config SETTINGS_ZMS_LL_CACHE_SIZE
75+
int "ZMS linked list lookup cache size"
76+
default 128
77+
range 1 $(UINT32_MAX)
78+
depends on SETTINGS_ZMS_LL_CACHE
79+
help
80+
Number of entries in Settings ZMS linked list cache.
81+
6782
endif # SETTINGS_ZMS
6883

6984
config SETTINGS_FCB

subsys/settings/include/settings/settings_zms.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ extern "C" {
7777
#define ZMS_COLLISION_NUM(x) ((x & ZMS_COLLISIONS_MASK) >> 1)
7878
#define ZMS_NAME_ID_FROM_HASH(x) ((x & ZMS_HASH_TOTAL_MASK) | BIT(31))
7979

80+
struct settings_hash_linked_list {
81+
uint32_t previous_hash;
82+
uint32_t next_hash;
83+
};
84+
8085
struct settings_zms {
8186
struct settings_store cf_store;
8287
struct zms_fs cf_zms;
@@ -89,16 +94,16 @@ struct settings_zms {
8994

9095
uint32_t cache_next;
9196
#endif
97+
#if CONFIG_SETTINGS_ZMS_LL_CACHE
98+
struct settings_hash_linked_list ll_cache[CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE];
99+
uint32_t ll_cache_next;
100+
bool ll_has_changed;
101+
#endif /* CONFIG_SETTINGS_ZMS_LL_CACHE */
92102
uint32_t last_hash_id;
93103
uint32_t second_to_last_hash_id;
94104
uint8_t hash_collision_num;
95105
};
96106

97-
struct settings_hash_linked_list {
98-
uint32_t previous_hash;
99-
uint32_t next_hash;
100-
};
101-
102107
#ifdef __cplusplus
103108
}
104109
#endif

subsys/settings/src/settings_zms.c

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
171171
return rc;
172172
}
173173
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
174+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
175+
cf->ll_has_changed = true;
176+
#endif
174177
rc = settings_zms_unlink_ll_node(cf, name_hash);
175178
if (rc < 0) {
176179
return rc;
@@ -268,11 +271,24 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
268271
}
269272
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
270273

274+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
275+
uint32_t ll_cache_index = 0;
276+
277+
if (cf->ll_has_changed) {
278+
/* reload the linked list in cache */
279+
ret = settings_zms_get_last_hash_ids(cf);
280+
if (ret < 0) {
281+
return ret;
282+
}
283+
}
284+
settings_element = cf->ll_cache[ll_cache_index++];
285+
#else
271286
ret = zms_read(&cf->cf_zms, ZMS_LL_HEAD_HASH_ID, &settings_element,
272287
sizeof(struct settings_hash_linked_list));
273288
if (ret < 0) {
274289
return ret;
275290
}
291+
#endif /* CONFIG_SETTINGS_ZMS_LL_CACHE */
276292
ll_hash_id = settings_element.next_hash;
277293

278294
/* If subtree is NULL then we must load all found Settings */
@@ -302,12 +318,19 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
302318
return ret;
303319
}
304320
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
305-
306-
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
307-
sizeof(struct settings_hash_linked_list));
308-
if (ret < 0) {
309-
return ret;
321+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
322+
if (ll_cache_index < cf->ll_cache_next) {
323+
settings_element = cf->ll_cache[ll_cache_index++];
324+
} else {
325+
#endif
326+
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
327+
sizeof(struct settings_hash_linked_list));
328+
if (ret < 0) {
329+
return ret;
330+
}
331+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
310332
}
333+
#endif
311334
/* update next ll_hash_id */
312335
ll_hash_id = settings_element.next_hash;
313336
continue;
@@ -334,12 +357,20 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
334357
break;
335358
}
336359

337-
/* update next ll_hash_id */
338-
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
339-
sizeof(struct settings_hash_linked_list));
340-
if (ret < 0) {
341-
return ret;
360+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
361+
if (ll_cache_index < cf->ll_cache_next) {
362+
settings_element = cf->ll_cache[ll_cache_index++];
363+
} else {
364+
#endif
365+
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
366+
sizeof(struct settings_hash_linked_list));
367+
if (ret < 0) {
368+
return ret;
369+
}
370+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
342371
}
372+
#endif
373+
/* update next ll_hash_id */
343374
ll_hash_id = settings_element.next_hash;
344375
}
345376

@@ -500,6 +531,11 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
500531
if (rc < 0) {
501532
return rc;
502533
}
534+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
535+
if (cf->ll_cache_next <= CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) {
536+
cf->ll_cache[cf->ll_cache_next++] = settings_element;
537+
}
538+
#endif
503539
/* Now update the previous linked list element */
504540
settings_element.next_hash = name_hash | 1;
505541
settings_element.previous_hash = cf->second_to_last_hash_id;
@@ -510,6 +546,12 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
510546
}
511547
cf->second_to_last_hash_id = cf->last_hash_id;
512548
cf->last_hash_id = name_hash | 1;
549+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
550+
if ((cf->ll_cache_next <= CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) &&
551+
(cf->ll_cache_next > 1)) {
552+
cf->ll_cache[cf->ll_cache_next - 2] = settings_element;
553+
}
554+
#endif
513555
}
514556
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
515557
no_ll_update:
@@ -532,6 +574,10 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
532574
uint32_t ll_last_hash_id = ZMS_LL_HEAD_HASH_ID;
533575
int rc = 0;
534576

577+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
578+
cf->ll_cache_next = 0;
579+
cf->ll_has_changed = false;
580+
#endif
535581
cf->hash_collision_num = 0;
536582
do {
537583
rc = zms_read(&cf->cf_zms, ll_last_hash_id, &settings_element,
@@ -547,11 +593,21 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
547593
}
548594
cf->last_hash_id = ZMS_LL_HEAD_HASH_ID;
549595
cf->second_to_last_hash_id = 0;
596+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
597+
/* store the LL header in cache */
598+
cf->ll_cache_next = 0;
599+
cf->ll_cache[cf->ll_cache_next++] = settings_element;
600+
#endif
550601
return 0;
551602
} else if (rc < 0) {
552603
return rc;
553604
}
554605

606+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
607+
if (cf->ll_cache_next <= CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) {
608+
cf->ll_cache[cf->ll_cache_next++] = settings_element;
609+
}
610+
#endif
555611
/* increment hash collision number if necessary */
556612
if (ZMS_COLLISION_NUM(ll_last_hash_id) > cf->hash_collision_num) {
557613
cf->hash_collision_num = ZMS_COLLISION_NUM(ll_last_hash_id);

0 commit comments

Comments
 (0)