Skip to content

Commit cba1324

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 410a0a505cd93d0382a51a58e6317a7ef46c6145)
1 parent 3a7a45d commit cba1324

File tree

3 files changed

+94
-15
lines changed

3 files changed

+94
-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: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
172172
return rc;
173173
}
174174
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
175+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
176+
cf->ll_has_changed = true;
177+
#endif
175178
rc = settings_zms_unlink_ll_node(cf, name_hash);
176179
if (rc < 0) {
177180
return rc;
@@ -269,11 +272,24 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
269272
}
270273
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
271274

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

279295
/* If subtree is NULL then we must load all found Settings */
@@ -303,12 +319,19 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
303319
return ret;
304320
}
305321
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
306-
307-
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
308-
sizeof(struct settings_hash_linked_list));
309-
if (ret < 0) {
310-
return ret;
322+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
323+
if (ll_cache_index < cf->ll_cache_next) {
324+
settings_element = cf->ll_cache[ll_cache_index++];
325+
} else {
326+
#endif
327+
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
328+
sizeof(struct settings_hash_linked_list));
329+
if (ret < 0) {
330+
return ret;
331+
}
332+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
311333
}
334+
#endif
312335
/* update next ll_hash_id */
313336
ll_hash_id = settings_element.next_hash;
314337
continue;
@@ -335,12 +358,20 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
335358
break;
336359
}
337360

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

@@ -501,6 +532,12 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
501532
if (rc < 0) {
502533
return rc;
503534
}
535+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
536+
if (cf->ll_cache_next < CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) {
537+
cf->ll_cache[cf->ll_cache_next] = settings_element;
538+
cf->ll_cache_next = cf->ll_cache_next + 1;
539+
}
540+
#endif
504541
/* Now update the previous linked list element */
505542
settings_element.next_hash = name_hash | 1;
506543
settings_element.previous_hash = cf->second_to_last_hash_id;
@@ -511,6 +548,12 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
511548
}
512549
cf->second_to_last_hash_id = cf->last_hash_id;
513550
cf->last_hash_id = name_hash | 1;
551+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
552+
if ((cf->ll_cache_next < CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) &&
553+
(cf->ll_cache_next > 1)) {
554+
cf->ll_cache[cf->ll_cache_next - 2] = settings_element;
555+
}
556+
#endif
514557
}
515558
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
516559
no_ll_update:
@@ -533,6 +576,10 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
533576
uint32_t ll_last_hash_id = ZMS_LL_HEAD_HASH_ID;
534577
int rc = 0;
535578

579+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
580+
cf->ll_cache_next = 0;
581+
cf->ll_has_changed = false;
582+
#endif
536583
cf->hash_collision_num = 0;
537584
do {
538585
rc = zms_read(&cf->cf_zms, ll_last_hash_id, &settings_element,
@@ -548,11 +595,23 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
548595
}
549596
cf->last_hash_id = ZMS_LL_HEAD_HASH_ID;
550597
cf->second_to_last_hash_id = 0;
598+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
599+
/* store the LL header in cache */
600+
cf->ll_cache_next = 0;
601+
cf->ll_cache[cf->ll_cache_next] = settings_element;
602+
cf->ll_cache_next = cf->ll_cache_next + 1;
603+
#endif
551604
return 0;
552605
} else if (rc < 0) {
553606
return rc;
554607
}
555608

609+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
610+
if (cf->ll_cache_next < CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) {
611+
cf->ll_cache[cf->ll_cache_next] = settings_element;
612+
cf->ll_cache_next = cf->ll_cache_next + 1;
613+
}
614+
#endif
556615
/* increment hash collision number if necessary */
557616
if (ZMS_COLLISION_NUM(ll_last_hash_id) > cf->hash_collision_num) {
558617
cf->hash_collision_num = ZMS_COLLISION_NUM(ll_last_hash_id);

0 commit comments

Comments
 (0)