Skip to content

Commit 5c38c58

Browse files
rghaddabkartben
authored andcommitted
zms: optimize cache for settings subsystem
Settings subsystem is storing the name ID and the linked list node ID with only one bit difference at BIT(0). Settings subsystem is also storing the name ID and the data ID in two different ZMS entries at an exact offset of ZMS_DATA_ID_OFFSET. Using the regular lookup function could result in many cache misses. Therefore, to assure the least number of collisions in the lookup cache, the BIT(0) of the hash indicates whether the given ZMS ID represents a linked list entry or not, the BIT(1) indicates whether the ZMS ID is a name or data and the remaining bits of the hash are set to a truncated part of the original hash generated by Settings. Signed-off-by: Riadh Ghaddab <[email protected]>
1 parent 42b9b5a commit 5c38c58

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
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_CUSTOM_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 && SETTINGS_ZMS
56+
help
57+
Enable usage of lookup cache based on hashes to get, the best ZMS performance,
58+
provided that the ZMS is used only for the purpose of providing the settings
59+
backend. This option should NOT be enabled if the ZMS is also written to
60+
directly, outside the settings layer.
61+
5362
config ZMS_NO_DOUBLE_WRITE
5463
bool "Avoid writing the same data again in the storage"
5564
help

subsys/fs/zms/zms.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <zephyr/fs/zms.h>
1313
#include <zephyr/sys/crc.h>
1414
#include "zms_priv.h"
15+
#ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS
16+
#include <settings/settings_zms.h>
17+
#endif
1518

1619
#include <zephyr/logging/log.h>
1720
LOG_MODULE_REGISTER(fs_zms, CONFIG_ZMS_LOG_LEVEL);
@@ -28,15 +31,41 @@ static int zms_ate_valid_different_sector(struct zms_fs *fs, const struct zms_at
2831

2932
static inline size_t zms_lookup_cache_pos(uint32_t id)
3033
{
31-
uint32_t hash;
34+
uint32_t hash = id;
35+
36+
#ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS
37+
/*
38+
* 1. Settings subsystem is storing the name ID and the linked list node ID
39+
* with only one bit difference at BIT(0).
40+
* 2. Settings subsystem is also storing the name ID and the data ID in two
41+
* different ZMS entries at an exact offset of ZMS_DATA_ID_OFFSET.
42+
*
43+
* Therefore, to assure the least number of collisions in the lookup cache,
44+
* the BIT(0) of the hash indicates whether the given ZMS ID represents a
45+
* linked list entry or not, the BIT(1) indicates whether the ZMS ID is a name
46+
* or data and the remaining bits of the hash are set to a truncated part of the
47+
* original hash generated by Settings.
48+
*/
3249

50+
BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_DATA_ID_OFFSET), "ZMS_DATA_ID_OFFSET is not power of 2");
51+
52+
uint32_t key_value_bit;
53+
uint32_t key_value_hash;
54+
uint32_t key_value_ll;
55+
56+
key_value_bit = (id >> LOG2(ZMS_DATA_ID_OFFSET)) & 1;
57+
key_value_hash = (id & ZMS_HASH_MASK) >> (CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS + 1);
58+
key_value_ll = id & BIT(0);
59+
60+
hash = (key_value_hash << 2) | (key_value_bit << 1) | key_value_ll;
61+
#else
3362
/* 32-bit integer hash function found by https://github.com/skeeto/hash-prospector. */
34-
hash = id;
3563
hash ^= hash >> 16;
3664
hash *= 0x7feb352dU;
3765
hash ^= hash >> 15;
3866
hash *= 0x846ca68bU;
3967
hash ^= hash >> 16;
68+
#endif /* CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS */
4069

4170
return hash % CONFIG_ZMS_LOOKUP_CACHE_SIZE;
4271
}

0 commit comments

Comments
 (0)