[redis源码]LZF压缩算法

作者云课堂:http://m.study.163.com/provider/480000001930416/index.htm?share=2&shareId=480000001930416

文件

lzf.h
lzfP.h
lzf_c.c (压缩)
lzf_d.c (解压)

压缩

  • 默认模式是VERY_FAST

  • 核心思想

    • 对重复值进行压缩
    • 通过hash表来判断是否重复数据
  • 三种模式
模式(压缩)时间(压缩后)空间
ULTRA_FAST极端快
VERY_FAST非常快
普通
  • 变量

LZF_HSLOT_BIAS 64位系统,是in_data的起始地址
ip 输入游标
op 输出游标
hval 整型,当前游标的4位数值ip[-1]|ip[0]|ip[1]|ip[2]
htab 保存输入数据(in_data)的下标
hslot 哈希槽,指向哈希表(htab)的指针
ref 值引用,ref = *hslot + LZF_HSLOT_BIAS,也是引用in_data的数据
off 偏移量,ip相对于ref的偏移量
lit literal,非压缩字符串长度

  • 流程图

在这里插入图片描述

  • 代码段
  • 片段1
/*
    * 索引到非压缩字符串前一个字节,将其长度写进该地址
    * 如果此压缩字符串前也是压缩字符串,则回溯前一个字节
    * 例如000LLLLL和0000LLLL0000
*/
op [- lit - 1] = lit - 1; /* stop run */
op -= !lit; /* undo run if length is zero */
  • 片段2
/*
    * 允许程序员将最有可能执行的分支告诉编译器;减少指令跳转
*/
expect_false(expr)
expect_true(expr)
__builtin_expect(EXP, N)
  • 片段3
/*
    有三个点需要说明一下:
    1、长度小于7,偏移量的高5位保存在op[0]低5位;长度保存在高三位
    2、大于等于7,偏移量的高5位保存在op[0]低5位;7(111)保存在高三位。长度减去7保存在op[1]
    3、剩余的偏移量低8位,保存在op[2]
*/
if (len < 7)
{
    *op++ = (off >> 8) + (len << 5);
}
else
{
    *op++ = (off >> 8) + (  7 << 5);
    *op++ = len - 7;
}

*op++ = off;
5b3b/11b8b
off高5位lenoff低8位
  • 例子
原始数据压缩后数据
000 30
0001 30 30
00002 30 30 30
000L03 30 30 30 4C
000LL04 30 30 30 4C 4C
000LLL05 30 30 30 4C 4C 4C
000LLLL03 30 30 30 4C 20 00
000LLLLL03 30 30 30 4C 20 00 00 4C

解压

  • 流程图

在这里插入图片描述

  • 代码段
  • 片段1
/*
    * 获取集中在的长度
    * 根据保存的偏移量,获取引用ref
*/
    unsigned int len = ctrl >> 5;

    u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;

#if CHECK_INPUT
    if (ip >= in_end)
    {
        SET_ERRNO (EINVAL);
        return 0;
    }
#endif
    if (len == 7)
    {
        len += *ip++;
#if CHECK_INPUT
        if (ip >= in_end)
        {
            SET_ERRNO (EINVAL);
            return 0;
        }
#endif
    }

    ref -= *ip++;
  • 片段2
/*
    这里需要注意的是:
    ref是op的引用,也就是输出数据的引用;因此也就是数据的自我复制。
*/
case 9: *op++ = *ref++; /* fall-thru */
case 8: *op++ = *ref++; /* fall-thru */
case 7: *op++ = *ref++; /* fall-thru */
case 6: *op++ = *ref++; /* fall-thru */
case 5: *op++ = *ref++; /* fall-thru */
case 4: *op++ = *ref++; /* fall-thru */
case 3: *op++ = *ref++; /* fall-thru */
case 2: *op++ = *ref++; /* fall-thru */
case 1: *op++ = *ref++; /* fall-thru */
case 0: *op++ = *ref++; /* two octets more */
        *op++ = *ref++; /* fall-thru */
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值