Skip to content

Commit 1dc8344

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 73f9ce636edeccb3edbf205cedc604c71427d079)
1 parent e772161 commit 1dc8344

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;
@@ -244,11 +247,24 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
244247
}
245248
}
246249
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
250+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
251+
uint32_t ll_cache_index = 0;
252+
253+
if (cf->ll_has_changed) {
254+
/* reload the linked list in cache */
255+
ret = settings_zms_get_last_hash_ids(cf);
256+
if (ret < 0) {
257+
return ret;
258+
}
259+
}
260+
settings_element = cf->ll_cache[ll_cache_index++];
261+
#else
247262
ret = zms_read(&cf->cf_zms, ZMS_LL_HEAD_HASH_ID, &settings_element,
248263
sizeof(struct settings_hash_linked_list));
249264
if (ret < 0) {
250265
return ret;
251266
}
267+
#endif /* CONFIG_SETTINGS_ZMS_LL_CACHE */
252268
ll_hash_id = settings_element.next_hash;
253269

254270
/* If subtree is NULL then we must load all found Settings */
@@ -278,12 +294,19 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
278294
return ret;
279295
}
280296
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
281-
282-
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
283-
sizeof(struct settings_hash_linked_list));
284-
if (ret < 0) {
285-
return ret;
297+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
298+
if (ll_cache_index < cf->ll_cache_next) {
299+
settings_element = cf->ll_cache[ll_cache_index++];
300+
} else {
301+
#endif
302+
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
303+
sizeof(struct settings_hash_linked_list));
304+
if (ret < 0) {
305+
return ret;
306+
}
307+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
286308
}
309+
#endif
287310
/* update next ll_hash_id */
288311
ll_hash_id = settings_element.next_hash;
289312
continue;
@@ -310,12 +333,20 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
310333
break;
311334
}
312335

313-
/* update next ll_hash_id */
314-
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
315-
sizeof(struct settings_hash_linked_list));
316-
if (ret < 0) {
317-
return ret;
336+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
337+
if (ll_cache_index < cf->ll_cache_next) {
338+
settings_element = cf->ll_cache[ll_cache_index++];
339+
} else {
340+
#endif
341+
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
342+
sizeof(struct settings_hash_linked_list));
343+
if (ret < 0) {
344+
return ret;
345+
}
346+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
318347
}
348+
#endif
349+
/* update next ll_hash_id */
319350
ll_hash_id = settings_element.next_hash;
320351
}
321352

@@ -476,6 +507,11 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
476507
if (rc < 0) {
477508
return rc;
478509
}
510+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
511+
if (cf->ll_cache_next <= CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) {
512+
cf->ll_cache[cf->ll_cache_next++] = settings_element;
513+
}
514+
#endif
479515
/* Now update the previous linked list element */
480516
settings_element.next_hash = name_hash | 1;
481517
settings_element.previous_hash = cf->second_to_last_hash_id;
@@ -486,6 +522,12 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
486522
}
487523
cf->second_to_last_hash_id = cf->last_hash_id;
488524
cf->last_hash_id = name_hash | 1;
525+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
526+
if ((cf->ll_cache_next <= CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) &&
527+
(cf->ll_cache_next > 1)) {
528+
cf->ll_cache[cf->ll_cache_next - 2] = settings_element;
529+
}
530+
#endif
489531
}
490532
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
491533
no_ll_update:
@@ -508,6 +550,10 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
508550
uint32_t ll_last_hash_id = ZMS_LL_HEAD_HASH_ID;
509551
int rc = 0;
510552

553+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
554+
cf->ll_cache_next = 0;
555+
cf->ll_has_changed = false;
556+
#endif
511557
cf->hash_collision_num = 0;
512558
do {
513559
rc = zms_read(&cf->cf_zms, ll_last_hash_id, &settings_element,
@@ -523,11 +569,21 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
523569
}
524570
cf->last_hash_id = ZMS_LL_HEAD_HASH_ID;
525571
cf->second_to_last_hash_id = 0;
572+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
573+
/* store the LL header in cache */
574+
cf->ll_cache_next = 0;
575+
cf->ll_cache[cf->ll_cache_next++] = settings_element;
576+
#endif
526577
return 0;
527578
} else if (rc < 0) {
528579
return rc;
529580
}
530581

582+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
583+
if (cf->ll_cache_next <= CONFIG_SETTINGS_ZMS_LL_CACHE_SIZE) {
584+
cf->ll_cache[cf->ll_cache_next++] = settings_element;
585+
}
586+
#endif
531587
/* increment hash collision number if necessary */
532588
if (ZMS_COLLISION_NUM(ll_last_hash_id) > cf->hash_collision_num) {
533589
cf->hash_collision_num = ZMS_COLLISION_NUM(ll_last_hash_id);

0 commit comments

Comments
 (0)