【博客477】prometheus-----数值数据编码(varint与zigzag)

news/2024/10/23 9:38:14/

prometheus-----数据编码(varint与zigzag)

prometheus对数值数据进行编码时,使用到了varint与zigzag

varint与zigzag编码方法在protobuf中也被使用

prometheus encoding代码:

https://github.com/prometheus/prometheus/blob/main/tsdb/encoding/encoding.go

...
...
func (d *Decbuf) Varint64() int64 {if d.E != nil {return 0}// Decode as unsigned first, since that's what the varint library implements.ux, n := varint.Uvarint(d.B)if n < 1 {d.E = ErrInvalidSizereturn 0}// Now decode "ZigZag encoding" https://developers.google.com/protocol-buffers/docs/encoding#signed_integers.x := int64(ux >> 1)if ux&1 != 0 {x = ^x}d.B = d.B[n:]return x
}
...
...

varint编码

前言

传统的integer是以32位来表示的,存储在计算机中不管多大的数字都需要4个字节,而一个字节能表示256以内的数字,两个字节能表示65536以内的数字,在固定范围内只用一个或者两个字节表示岂不节省很大的空间。铛铛铛,varint就是根据这种思想来序列化整数的。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 varint 后,可以用更少的字节数来表示数字信息,从而实现数据的压缩。

简介

简单来说varint是一种数据压缩算法,其核心思想是利用bit位来实现数据的压缩。使用一个或多个字节序列化整数的方法。较小的数字占用较少的字节数。

优点:

Varint是一种使用一个或多个字节序列化整数的方法,会把整数编码为变长字节。对于32位整型数据经过Varint编码后需要1-5个字节,小的数字使用1个byte,大的数字使用5个bytes。64位整型数据编码后占用1~10个字节。在实际场景中小数字的使用率远远多于大数字,因此通过Varint编码对于大部分场景都可以起到很好的压缩效果。

原理

除了最后一个字节外,varint编码中的每个字节都设置了最高有效位(msb),msb为1则表明后面的字节还是属于当前数据的,如果是0那么这是当前数据的最后一个字节数据。每个字节的低7位用于以7位为一组存储数字的二进制补码表示,最低有效组在前,或者叫最低有效字节在前。

除了最后一个字节外,varint编码中的每个字节都设置了最高有效位(most significant bit - msb)–msb为1则表明后面的字节还是属于当前数据的,如果是0那么这是当前数据的最后一个字节数据。每个字节的低7位用于以7位为一组存储数字的二进制补码表示,最低有效组在前,或者叫最低有效字节在前。这表明varint编码后数据的字节是按照小端序排列的。

例如:

这里是数字128,它是一个字节,因此未设置msb:01111111

这是300的表示方式1010 1100 0000 0010,它就显示稍微复杂些,您如何确定这是300?

首先取出第一个字节1010 1100最高位为1,表明接下来一个字节是一起的,然后取出紧跟着的一个字节0000 0010发现该字节最高位为0,则表明没有后续。因为varint是最低有效组在前,所以去掉第一个字节的最高位,然后去掉第二个字节的最高位放在第一个字节处理后的数值前面形成100101100 ,如下图所示:

在这里插入图片描述

zigzag编码

前言:

前面说到varint算法是一种紧凑的压缩数据方法,对于比较小的数值压缩效率很高,但是对于大的数据效率不但没有提升可能还会有所下降。而负数在计算机中的表示就是一个很大的数值。为了达到压缩效果就需要一个方法,把负数转换成小的正数的方法,而zigzag算法正好解决这个需求。

基础知识:原码,反码和补码

在这里插入图片描述
在这里插入图片描述

编码原理

负数的问题引入:
在这里插入图片描述

zigzag巧妙解决方法:

在这里插入图片描述

ZigZag编码将有符号整数映射为无符号整数,以便具有较小绝对值(例如-1)的数字也具有较小的编码值。这样做的方式是通过正整数和负整数来回“曲折”,以便将-1编码为1,将1编码为2,将-2编码为3,依此类推如下图所示。在这里插入图片描述
result:
在这里插入图片描述

zigzag编码实现:

在这里插入图片描述

example:

package mainimport "fmt"func zigzag(n int) int {return (n << 1) ^ (n >> 31)
}func main() {fmt.Println("result of zigzag -1:", zigzag(-1))fmt.Println("result of zigzag  1:", zigzag(1))fmt.Println("result of zigzag -2:", zigzag(-2))fmt.Println("result of zigzag  2:", zigzag(2))fmt.Println("result of zigzag -3:", zigzag(-3))fmt.Println("result of zigzag  3:", zigzag(3))
}// go run main.go
result of zigzag -1: 1
result of zigzag  1: 2
result of zigzag -2: 3
result of zigzag  2: 4
result of zigzag -3: 5
result of zigzag  3: 6

总结

无符号数:

对正整数进行编码的时候可以使用varint编码来节省前缀0

有符号数:

对有符号整数进行编码的时候,可以使用zigzag来消除负数情况下数值很大的问题,通过zigzag对有符号数字进行编码后,使得正负数都变成了正数表示形式,此时再通过varint进行编码来节省前缀0


http://www.ppmy.cn/news/535622.html

相关文章

​LeetCode刷题实战477:汉明距离总和

算法的重要性&#xff0c;我就不多说了吧&#xff0c;想去大厂&#xff0c;就必须要经过基础知识和业务逻辑面试算法面试。所以&#xff0c;为了提高大家的算法能力&#xff0c;这个公众号后续每天带大家做一道算法题&#xff0c;题目就从LeetCode上面选 &#xff01; 今天和大…

LeetCode 算法 每日一题 477.汉明距离总和

10.正则表达式匹配 题目描述 两个整数的汉明距离指的是这两个数字的二进制数对应位不同的数量。 计算一个数组中&#xff0c;任意两个数之间汉明距离的总和。 示例1 输入: 4, 14, 2 输出: 6 解释: 在二进制表示中&#xff0c;4表示为0100&#xff0c;14表示为1110&#xff0…

奇舞周刊 477 期:一文弄懂 React ref 原理

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 一文弄懂 React ref 原理 对于 Ref 理解与使用&#xff0c;一些读者可能还停留在用 ref 获取真实 DOM 元素和获取类组件实例层面上 其实 ref 除了这两项常用功能之外&#xff0c;还…

Java实现 LeetCode 477 汉明距离总和

477. 汉明距离总和 两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。 计算一个数组中&#xff0c;任意两个数之间汉明距离的总和。 示例: 输入: 4, 14, 2 输出: 6 解释: 在二进制表示中&#xff0c;4表示为0100&#xff0c;14表示为1110&#xff0c;2表…

leetcode 477.汉明距离总和

每日一题 昨天做了道相似的汉明距离详见leetcode461&#xff0c;今天又看见类似的题目准备重拳出击&#xff01; 博主技术有限…于是直接暴力 class Solution {public int totalHammingDistance(int[] nums) {int sum 0;int total 0;for(int i 0;i < nums.length;i){for…

leetcode 477 汉明距离总和(位运算、排列组合)

题目描述&#xff1a; 两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。 计算一个数组中&#xff0c;任意两个数之间汉明距离的总和。 示例: 输入: 4, 14, 2 输出: 6 解释: 在二进制表示中&#xff0c;4表示为0100&#xff0c;14表示为1110&#xff0c;…

【CodeForces】CodeForces Round #477 (Div. 1 + Div. 2) 题解

【比赛链接】 Div. 1Div. 2 【题解链接】 点击打开链接 【Div.2 A】Mind the Gap 【思路要点】 从小到大枚举答案&#xff0c;检查合法性。时间复杂度\(O(Ans*N)\)。 【代码】 #include<bits/stdc.h> using namespace std; const int MAXN 100005; template <typena…

【C语言刷LeetCode】477. 汉明距离总和(M)

【 两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。 给你一个整数数组 nums&#xff0c;请你计算并返回 nums 中任意两个数之间 汉明距离的总和 。 示例 1&#xff1a; 输入&#xff1a;nums [4,14,2] 输出&#xff1a;6 解释&#xff1a;在二进制表示中…