4)计算 bit=(offset mod 8)+1;bit 值表示在 byte 下标字节的第几个二进制位;
5)根据 byte 和 bit 的值定位 offfset 偏移量指定的二进制位 oldvalue,并修改;
6)向客户端返回二进制位 oldvalue 的值;
无扩展操作的 SETBIT 命令示例如下:
带扩展操作的 SETBIT 命令示例如下: 1.4 BITECOUNT 命令的实现
遍历算法:
遍历位数组中的每个二进制位,遇到 1 时将计数器值赠 1;
实现简单,效率低;
查表法:
对于长度有限的位数组而言,能表示的二进制位有限,而每种排列顺序的 1 的个数是确定的;
查表法是典型的空间换时间策略,节约时间越多,花费内存越大
受 CPU 缓存限制:创建表越大,能加载进缓存的内容越少,缓存不命中的情况越高,缓存的换入换出操作就越频繁,最终影响实际效率;
variable-precision SWAR 算法:
又称:计算汉明重量法;
一个处理 32 位长度位数的算法示例:
32_t swar(unit32_t i){
//步骤1:按每2个二进制位为一组分组,各组的十进制为汉明重量
i = (i & 0x55555555) + ((i >> 1) & 0x55555555);
//步骤2:按每4个二进制位为一组分组,各组的十进制为汉明重量
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
//步骤3:按每8个二进制位为一组分组,各组的十进制为汉明重量
i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F);
//步骤4
i = (i*(0x01010101) >> 24);
return i;
}
redisServer{
//...
// 下一条慢查询日志的 ID
long long slowlog_entry_id;
// 保存了所有慢查询日志的链表
list *slowlog;
// 服务器配置 slow_log_slower_than 选项的值
long long slow_log_slower_than;
// 服务器配置 slowlog_max_len 选项的值
unsigned long slowlog_max_len;
};
slowlog 链表结构如下:
struct slowlogEntry{
// 唯一标识符
long long id;
// 命令执行时的时间,格式为 UNIX 时间戳
time_t time;
// 执行命令消耗的时间,以微秒为单位
long long duration;
// 命令与命令参数
robj **argv;
// 命令与命令参数的数量
int argc;
} slowlogEntry;
2.2 慢查询日志的阅览与删除
SLOWLOG GET [number];打印所有 slow log ,最大长度取决于 slowlog-max-len 选项的值;