redis-dict-change

2021-11-29

issue:https://github.com/redis/redis/pull/9228

最近在看代码的时候发现redis的dict这个数据结构发生了很大的变化,对于redis来说dict结构十分重要,因而单开一个wiki来分析下这个变化。

image-20211129094956602

可以看到pr的开头写着就是针对dict数据结构内存的优化。

翻译:

减少dict结构的内存开销:
从原来的96到现在的56
修改:
1.从回调和dict移除'privdata'。(这个影响很多文件)
2.合并dictht结构到dict结构中,消除数据结构嵌套
3.删除sizemask,但可以计算大小当需要的时候
4.转换size到size_exp,从8字节到1字节。

原来结构:

typedef struct dictType {
    uint64_t (*hashFunction)(const void *key);
    void *(*keyDup)(void *privdata, const void *key);
    void *(*valDup)(void *privdata, const void *obj);
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
    int (*expandAllowed)(size_t moreMem, double usedRatio);
} dictType; 

/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new table. */
typedef struct dictht {
    dictEntry **table;		8
    unsigned long size;	8
    unsigned long sizemask;	8	
    unsigned long used;	8	
} dictht;

typedef struct dict {
    dictType *type;	8
    void *privdata; 8
    dictht ht[2];	32 * 2
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */	8
    int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */	2
} dict;

现在结构

typedef struct dictType {
    uint64_t (*hashFunction)(const void *key);
    void *(*keyDup)(dict *d, const void *key);
    void *(*valDup)(dict *d, const void *obj);
    int (*keyCompare)(dict *d, const void *key1, const void *key2);
    void (*keyDestructor)(dict *d, void *key);
    void (*valDestructor)(dict *d, void *obj);
    int (*expandAllowed)(size_t moreMem, double usedRatio);
    /* Allow a dictEntry to carry extra caller-defined metadata.  The
     * extra memory is initialized to 0 when a dictEntry is allocated. */
    size_t (*dictEntryMetadataBytes)(dict *d);
} dictType;

#define DICTHT_SIZE(exp) ((exp) == -1 ? 0 : (unsigned long)1<<(exp))
#define DICTHT_SIZE_MASK(exp) ((exp) == -1 ? 0 : (DICTHT_SIZE(exp))-1)

struct dict {
    dictType *type; 8

    dictEntry **ht_table[2]; 16
    unsigned long ht_used[2]; 16 

    long rehashidx; /* rehashing not in progress if rehashidx == -1 */ 8

    /* Keep small vars at end for optimal (minimal) struct padding */
    int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */ 2
    signed char ht_size_exp[2]; /* exponent of size. (size = 1<<exp) */	2
};
from fi_tempest_plugin.common.info_collect import InfoCollectUtil
from fi_tempest_plugin.services.info_collect import fuel_ostf
ostf_client = fuel_ostf.OstfClient()
test_set = "hw_health"
test_id = "fuel_health.tests.hw_health.cps.test_cps.CpsTest.test_components_consistence"
ret, response = ostf_client.do_tests([test_id], test_set)
test_run_id = response[0]
ret, response = ostf_client.get_test_run(test_run_id)