本节重点介绍 :
- xor 压缩value原理
- xor压缩过程讲解
- xor压缩prometheus源码解读
- xor 压缩效果
xor 压缩value原理
- 原理:时序数据库相邻点变化不大,采用异或压缩float64的前缀和后缀0个数
xor压缩过程讲解
- 第一个值使用原始点存储
- 计算和前面的值的xor
- 如果XOR值为0,即两个Value相同,那么存为’0’,只占用一个bit。
- 如果XOR为非0,首先计算XOR中位于前端的和后端的0的个数,即Leading Zeros与Trailing Zeros。
- 第一个bit值存为’1’。
- 如果Leading Zeros与Trailing Zeros与前一个XOR值相同,则第2个bit值存为’0’,而后,紧跟着去掉Leading Zeros与Trailing Zeros以后的有效XOR值部分。
- 如果Leading Zeros与Trailing Zeros与前一个XOR值不同,则第2个bit值存为’1’,而后,紧跟着5个bits用来描述Leading Zeros的值,再用6个bits来描述有效XOR值的长度,最后再存储有效XOR值部分(这种情形下,至少产生了13个bits的冗余信息)
xor压缩prometheus源码解读
- xorAppender.Append 中调用的writeVDelta ,位置 D:\go_path\src\github.com\prometheus\prometheus\tsdb\chunkenc\xor.go
- vDelta代表xor的结果值,然后进行判断
func (a *xorAppender) writeVDelta(v float64) {
vDelta := math.Float64bits(v) ^ math.Float64bits(a.v)
if vDelta == 0 {
a.b.writeBit(zero)
return
}
a.b.writeBit(one)
leading := uint8(bits.LeadingZeros64(vDelta))
trailing := uint8(bits.TrailingZeros64(vDelta))
if leading >= 32 {
leading = 31
}
if a.leading != 0xff && leading >= a.leading && trailing >= a.trailing {
a.b.writeBit(zero)
a.b.writeBits(vDelta>>a.trailing, 64-int(a.leading)-int(a.trailing))
} else {
a.leading, a.trailing = leading, trailing
a.b.writeBit(one)
a.b.writeBits(uint64(leading), 5)
sigbits := 64 - leading - trailing
a.b.writeBits(uint64(sigbits), 6)
a.b.writeBits(vDelta>>trailing, int(sigbits))
}
}
xor 压缩效果
- 从结果来看:
- 只占用1个bit的Value比例高达59.06%,这说明约一半以上的Point Value较之上一个Value并未发生变化。
- 30%比例的Value平均占用26.6 bits,即上面的情形2.1。
- 余下的12.64%的Value平均占用39.6 bits,即上面的情形2.2。
- 我认为xor压缩效果取决于series曲线波动情况,越剧烈压缩效果越差,越平滑压缩效果越好
本节重点总结 :
- xor 压缩value原理
- xor压缩过程讲解
- xor压缩prometheus源码解读
- xor 压缩效果