Lucene的Vint类型压缩

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

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

说明: 大致理解是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)");
}

 

posted @ 2018-07-30 21:32  車輪の唄  阅读(17)  评论(0编辑  收藏  举报  来源