Skip to content

Commit 549a4a5

Browse files
rghaddabgithub-actions[bot]
authored andcommitted
[nrf noup] settings: zms: use dedicated lookup cache hash function
Introduce ZMS_LOOKUP_CACHE_FOR_SETTINGS Kconfig option that enables a dedicated hash function for the ZMS lookup cache that takes advantage of the ZMS ID allocation scheme used by the ZMS settings backend. As such, this option should only be used if an application uses ZMS via the settings layer. Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit 6ccfcdc) (cherry picked from commit 810873e)
1 parent b6d6aad commit 549a4a5

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

subsys/fs/zms/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ config ZMS_MAX_BLOCK_SIZE
5050
help
5151
Changes the internal buffer size of ZMS
5252

53+
config ZMS_LOOKUP_CACHE_FOR_SETTINGS
54+
bool "ZMS Storage lookup cache optimized for settings"
55+
depends on ZMS_LOOKUP_CACHE
56+
help
57+
Use the lookup cache hash function that results in the least number of
58+
collissions and, in turn, the best ZMS performance provided that the ZMS
59+
is used as the settings backend only. This option should NOT be enabled
60+
if the ZMS is also written to directly, outside the settings layer.
61+
5362
module = ZMS
5463
module-str = zms
5564
source "subsys/logging/Kconfig.template.log_config"

subsys/fs/zms/zms.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <zephyr/fs/zms.h>
1212
#include <zephyr/sys/crc.h>
1313
#include "zms_priv.h"
14+
#ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS
15+
#include <zephyr/sys/util.h>
16+
#include <settings/settings_zms.h>
17+
#endif
1418

1519
#include <zephyr/logging/log.h>
1620
LOG_MODULE_REGISTER(fs_zms, CONFIG_ZMS_LOG_LEVEL);
@@ -25,6 +29,45 @@ static int zms_ate_valid_different_sector(struct zms_fs *fs, const struct zms_at
2529

2630
#ifdef CONFIG_ZMS_LOOKUP_CACHE
2731

32+
#ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS
33+
34+
static inline size_t zms_lookup_cache_pos(uint32_t id)
35+
{
36+
/*
37+
* 1. The ZMS settings backend uses up to (ZMS_NAME_ID_OFFSET - 1) ZMS IDs to
38+
store keys and equal number of ZMS IDs to store values.
39+
* 2. For each key-value pair, the value is stored at ZMS ID greater by exactly
40+
* ZMS_NAME_ID_OFFSET than ZMS ID that holds the key.
41+
* 3. The backend tries to minimize the range of ZMS IDs used to store keys.
42+
* That is, ZMS IDs are allocated sequentially, and freed ZMS IDs are reused
43+
* before allocating new ones.
44+
*
45+
* Therefore, to assure the least number of collisions in the lookup cache,
46+
* the least significant bit of the hash indicates whether the given ZMS ID
47+
* represents a key or a value, and remaining bits of the hash are set to
48+
* the ordinal number of the key-value pair. Consequently, the hash function
49+
* provides the following mapping:
50+
*
51+
* 1st settings key => hash 0
52+
* 1st settings value => hash 1
53+
* 2nd settings key => hash 2
54+
* 2nd settings value => hash 3
55+
* ...
56+
*/
57+
BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAMECNT_ID), "ZMS_NAMECNT_ID is not power of 2");
58+
BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAME_ID_OFFSET), "ZMS_NAME_ID_OFFSET is not power of 2");
59+
60+
uint32_t key_value_bit;
61+
uint32_t key_value_ord;
62+
63+
key_value_bit = (id >> LOG2(ZMS_NAME_ID_OFFSET)) & 1;
64+
key_value_ord = id & (ZMS_NAME_ID_OFFSET - 1);
65+
66+
return ((key_value_ord << 1) | key_value_bit) % CONFIG_ZMS_LOOKUP_CACHE_SIZE;
67+
}
68+
69+
#else /* CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS */
70+
2871
static inline size_t zms_lookup_cache_pos(uint32_t id)
2972
{
3073
uint32_t hash;
@@ -40,6 +83,8 @@ static inline size_t zms_lookup_cache_pos(uint32_t id)
4083
return hash % CONFIG_ZMS_LOOKUP_CACHE_SIZE;
4184
}
4285

86+
#endif /* CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS */
87+
4388
static int zms_lookup_cache_rebuild(struct zms_fs *fs)
4489
{
4590
int rc, previous_sector_num = ZMS_INVALID_SECTOR_NUM;

0 commit comments

Comments
 (0)