Lucene DataOutput中的VInt(可变长度整型)Vlong (可变长长整型)

1.vint,vlong是什么

lucene实现了可变长度int,使用1-5个字节存放一个int类型的数据,正常的int类型是4个字节,

2.vint,vlong策略

Vint压缩策略是,用每个字节的最高位做标志位,后7位为有效算术位,如果标志位为1,则说明后一个字节和当前字节是同一个数字,为0说明后一个字节是一个新的数字

VInt Encoding Example

Value

First byte

Second byte

Third byte

0

00000000

 

 

1

00000001

 

 

2

00000010

 

 

...

 

 

 

127

01111111

 

 

128

10000000

00000001

 

129

10000001

00000001

 

130

10000010

00000001

 

...

 

 

 

16,383

11111111

01111111

 

16,384

10000000

10000000

00000001

16,385

10000001

10000000

00000001

...

 

 

 

 

说明: 大致理解是VINT每个字节8位,第一位表示后面的字节是否属于这个int,后面7位正常表示int值,

例如:

16,383

11111111

01111111

这一个这么解释: 第一个字节的第一位为1: 则后面的字节计入int,

第二个字节的第一位为0,则后面的字节不计入int,

该int的值为 第一个自己的后7位+第二个字节的后7位。 11111111111111(2进制) =  16383(10进制);

java的二进制里,是用 0 和 1 来表示正负的,最高位为符号位,最高位为 1 代表负数,最高位为 0 代表正数。

VINT压缩效率:

1个字节:0~127

2个字节:  -127~0 和 127~16383

3个字节: -16383~-127 和 16363~2097151

4个字节: -2097151~-16383 和  2097151~268435455

5个字节: 7*5=35 > 32(位) 范围比整个int还要大,不过因为转化的值是存到int里,所以这里的范围就是int

压缩率根据数据组成不同而有差异

变长长整型和变长整型原理相同,位数加大了而已。

 

lucene-7.5.0写代码如下:

org.apache.lucene.store.DataOutput
public final void writeVInt(int i) throws IOException {
    while ((i & ~0x7F) != 0) {
      writeByte((byte)((i & 0x7F) | 0x80));
      i >>>= 7;
    }
    writeByte((byte)i);
  }

lucene-7.5.0 读代码如下:

org.apache.lucene.store.DataInput
public final int readVInt() throws IOException {
   /* This is the original code of this method,
     * but a Hotspot bug (see LUCENE-2975) corrupts the for-loop if
     * readByte() is inlined. So the loop was unwinded!
    byte b = readByte();
    int i = b & 0x7F;
    for (int shift = 7; (b & 0x80) != 0; shift += 7) {
      b = readByte();
      i |= (b & 0x7F) << shift;
    }
    return i;
    */
    byte b = readByte();
    if (b >= 0) return b;
    int i = b & 0x7F;
    b = readByte();
    i |= (b & 0x7F) << 7;
    if (b >= 0) return i;
    b = readByte();
    i |= (b & 0x7F) << 14;
    if (b >= 0) return i;
    b = readByte();
    i |= (b & 0x7F) << 21;
    if (b >= 0) return i;
    b = readByte();
    // Warning: the next ands use 0x0F / 0xF0 - beware copy/paste errors:
    i |= (b & 0x0F) << 28;
    if ((b & 0xF0) == 0) return i;
    throw new IOException("Invalid vInt detected (too many bits)");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值