Skip to content

Commit 711a8e7

Browse files
committed
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. Signed-off-by: Riadh Ghaddab <[email protected]>
1 parent 8e332c4 commit 711a8e7

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
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;
@@ -88,17 +93,17 @@ struct settings_zms {
8893
} cache[CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE];
8994

9095
uint32_t cache_next;
96+
#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;
91101
#endif
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: 60 additions & 1 deletion
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;
@@ -243,11 +246,24 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
243246
}
244247
}
245248
/* If subtree is NULL then we must load all found Settings */
249+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
250+
uint32_t ll_cache_index = 0;
251+
252+
if (cf->ll_has_changed) {
253+
/* reload the linked list in cache */
254+
ret = settings_zms_get_last_hash_ids(cf);
255+
if (ret < 0) {
256+
return ret;
257+
}
258+
}
259+
settings_element = cf->ll_cache[ll_cache_index++];
260+
#else
246261
ret = zms_read(&cf->cf_zms, ZMS_LL_HEAD_HASH_ID, &settings_element,
247262
sizeof(struct settings_hash_linked_list));
248263
if (ret < 0) {
249264
return ret;
250265
}
266+
#endif
251267
ll_hash_id = settings_element.next_hash;
252268

253269
while (ll_hash_id) {
@@ -275,13 +291,22 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
275291
if (ret < 0) {
276292
return ret;
277293
}
278-
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
294+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
279295
/* update next ll_hash_id */
296+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
297+
if (ll_cache_index < cf->ll_cache_next) {
298+
settings_element = cf->ll_cache[ll_cache_index++];
299+
} else {
300+
#else
280301
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
281302
sizeof(struct settings_hash_linked_list));
282303
if (ret < 0) {
283304
return ret;
284305
}
306+
#endif
307+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
308+
}
309+
#endif
285310
ll_hash_id = settings_element.next_hash;
286311
continue;
287312
}
@@ -307,12 +332,21 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
307332
break;
308333
}
309334

335+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
336+
if (ll_cache_index < cf->ll_cache_next) {
337+
settings_element = cf->ll_cache[ll_cache_index++];
338+
} else {
339+
#else
310340
/* update next ll_hash_id */
311341
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
312342
sizeof(struct settings_hash_linked_list));
313343
if (ret < 0) {
314344
return ret;
315345
}
346+
#endif
347+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
348+
}
349+
#endif
316350
ll_hash_id = settings_element.next_hash;
317351
}
318352

@@ -473,6 +507,11 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
473507
if (rc < 0) {
474508
return rc;
475509
}
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
476515
/* Now update the previous linked list element */
477516
settings_element.next_hash = name_hash | 1;
478517
settings_element.previous_hash = cf->second_to_last_hash_id;
@@ -483,6 +522,12 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
483522
}
484523
cf->second_to_last_hash_id = cf->last_hash_id;
485524
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
486531
}
487532
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
488533
no_ll_update:
@@ -505,6 +550,10 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
505550
uint32_t ll_last_hash_id = ZMS_LL_HEAD_HASH_ID;
506551
int rc = 0;
507552

553+
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
554+
cf->ll_cache_next = 0;
555+
cf->ll_has_changed = false;
556+
#endif
508557
cf->hash_collision_num = 0;
509558
do {
510559
rc = zms_read(&cf->cf_zms, ll_last_hash_id, &settings_element,
@@ -520,11 +569,21 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
520569
}
521570
cf->last_hash_id = ZMS_LL_HEAD_HASH_ID;
522571
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
523577
return 0;
524578
} else if (rc < 0) {
525579
return rc;
526580
}
527581

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
528587
/* increment hash collision number if necessary */
529588
if (ZMS_COLLISION_NUM(ll_last_hash_id) > cf->hash_collision_num) {
530589
cf->hash_collision_num = ZMS_COLLISION_NUM(ll_last_hash_id);

0 commit comments

Comments
 (0)