Skip to content

Commit ed2c313

Browse files
committed
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 e6443ae commit ed2c313

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
@@ -49,6 +49,15 @@ config ZMS_CUSTOM_BLOCK_SIZE
4949
help
5050
Changes the internal buffer size of ZMS
5151

52+
config ZMS_LOOKUP_CACHE_FOR_SETTINGS
53+
bool "ZMS Storage lookup cache optimized for settings"
54+
depends on ZMS_LOOKUP_CACHE && SETTINGS_ZMS
55+
help
56+
Use the lookup cache hash function that results in the least number of
57+
collissions and, in turn, the best ZMS performance provided that the ZMS
58+
is used as the settings backend only. This option should NOT be enabled
59+
if the ZMS is also written to directly, outside the settings layer.
60+
5261
config ZMS_NO_DOUBLE_WRITE
5362
bool "Avoid writing the same data again in the storage"
5463
help

subsys/fs/zms/zms.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
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 <settings/settings_zms.h>
16+
#endif
1417

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

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

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

4069
return hash % CONFIG_ZMS_LOOKUP_CACHE_SIZE;
4170
}

0 commit comments

Comments
 (0)