Redis设计与实现阅读 整数集合(六)

说明

redis整数集合 redis set的实现方式之一,当集合数量较小 同时又是数值类型 redis底层就是使用整数集合实现

本地:0>add number 2 3 4 5
4

本地:0>object encoding number
intset

本地:0>type number
set
本地:0>add number2  2 3 4 fds
4

本地:0>object encoding number2
hashtable

本地:0>type number2
set

整数集合的实现

typedef struct intset {

    // 编码方式 
    uint32_t encoding;

    // 集合包含的元素数量
    uint32_t length;

    // 保存元素的数组
    int8_t contents[];

} intset;

encoding的值为:INTSET_ENC_INT16,那么 contents 就是一个 int16_t 类型的数组, 数组里的每个项都是一个 int16_t 类型的整数值 (最小值为 -32,768 ,最大值为 32,767 )

encoding的值为:INTSET_ENC_INT32,那么 contents 就是一个 int32_t 类型的数组, 数组里的每个项都是一个 int32_t 类型的整数值 (最小值为 -2,147,483,648 ,最大值为 2,147,483,647 )。

encoding的值为:INTSET_ENC_INT64,那么 contents 就是一个 int64_t 类型的数组, 数组里的每个项都是一个 int64_t 类型的整数值 (最小值为 -9,223,372,036,854,775,808 ,最大值为 9,223,372,036,854,775,807 )

例子

 contents集合大小 为length*16  每个元素占16位

升级

当上面例子增加一个整数值为65535

集合将被扩展为32位 encoding的值变为INTSET_ENC_INT32   集合的大小变成5*32=160  同时将各个老元素从最后一个元素开始 从16位向后扩展为32位  复杂度为O(N)

扫描二维码关注公众号,回复: 7743469 查看本文章

升级的好处

升级的好处

整数集合的升级策略有两个好处, 一个是提升整数集合的灵活性, 另一个是尽可能地节约内存。

提升灵活性

因为 C 语言是静态类型语言, 为了避免类型错误, 我们通常不会将两种不同类型的值放在同一个数据结构里面。

比如说, 我们一般只使用 int16_t 类型的数组来保存 int16_t 类型的值, 只使用 int32_t 类型的数组来保存 int32_t 类型的值, 诸如此类。

但是, 因为整数集合可以通过自动升级底层数组来适应新元素, 所以我们可以随意地将 int16_t 、 int32_t 或者 int64_t 类型的整数添加到集合中, 而不必担心出现类型错误, 这种做法非常灵活。

节约内存

当然, 要让一个数组可以同时保存 int16_t 、 int32_t 、 int64_t 三种类型的值, 最简单的做法就是直接使用 int64_t 类型的数组作为整数集合的底层实现。 不过这样一来, 即使添加到整数集合里面的都是 int16_t 类型或者 int32_t 类型的值, 数组都需要使用 int64_t 类型的空间去保存它们, 从而出现浪费内存的情况。

而整数集合现在的做法既可以让集合能同时保存三种不同类型的值, 又可以确保升级操作只会在有需要的时候进行, 这可以尽量节省内存。

比如说, 如果我们一直只向整数集合添加 int16_t 类型的值, 那么整数集合的底层实现就会一直是 int16_t 类型的数组, 只有在我们要将 int32_t 类型或者 int64_t 类型的值添加到集合时, 程序才会对数组进行升级。

降级

比如现在将65535删除  各个元素还是会按32位占用 新加的元素也会按32位占用

猜你喜欢

转载自www.cnblogs.com/LQBlog/p/11793238.html