当前位置: 首页 > news >正文

Go中varint压缩编码原理分析

文章目录

    • 编码介绍
    • 无符号整数
      • 较小的值
      • 较大的值
      • Go中的实现
        • 编码PutUvarint
        • 解码Uvarint
    • 有符号整数
      • 较小的值(指绝对值)
      • 较大的负数(只绝对值)
      • Go中的实现
        • 编码PutVarint
        • 解码Varint
    • 总结

编码介绍

varint是一种将整数编码为变长字节的压缩编码算法,本篇文章就是分析该编码算法的原理以及看一看go中的源码实现。

计算机中,整型数据是按照补码进行存储的,varint编码的原理就是将整数按照7bits划分,在最高位设置一个有效位表示后面是否还有该整数的部分,当最高位为1时表示后面还有该数据的字节,为0表示该字节是最后一个字节。

无符号整数

较小的值

举个例子:对于一个uint32来说,无论数字多大,都会占用4个字节的大小空间。对0000 0000 0000 0000 0000 0000 0000 0001 进行编码:

  1. 首先将该数字按照7位进行分组
0000 0000000 0000000 0000000 0000001
  1. 依次从低字节开始读,发现只需要一个字节就能表示,后面没有可用的字节,最高位置0
0000 0001

所以最终对1的编码只占用一个字节

较大的值

0000 1111 1111 0000 1111 0000 1111 1111 进行编码

  1. 首先按照7bit进行分组
0000 1111111 1000011 1100001 1111111
  1. 依次读取低位字节进行编码
|  1111111 |  1100001 |  1000011 |  1111111 | 0000 || 11111111 | 11100001 | 11000011 | 01111111 |  

所以最终该数字占用 4 个字节

Go中的实现

go中关于varint编码的实现在binary包下,这里参考的是Go1.20

编码PutUvarint
func PutUvarint(buf []byte, x uint64) int {i := 0for x >= 0x80 {// 将该字节的最高位置 1, 表示后面还有数据buf[i] = byte(x) | 0x80// 将x向右移动7位(按照7bit进行分组的过程)x >>= 7i++}buf[i] = byte(x)return i + 1
}

循环条件就是判断当前x的值是否能用一个字节表示,大于0x80说明不能使用一个字节表示。

解码Uvarint
func Uvarint(buf []byte) (uint64, int) {var x uint64var s uint// 遍历buf中的每个字节,低位字节表示原数据的高位for i, b := range buf {// 如果i达到了64位数据所能编码的最大字节数,说明溢出if i == MaxVarintLen64 {// Catch byte reads past MaxVarintLen64.// See issue https://golang.org/issues/41185return 0, -(i + 1) // overflow}// 如果该字节小于0x80,说明该字节是最后一个有效字节if b < 0x80 {// 对于一个uint64的数据来说,64 % 7 = 1,所以最终只会多出1bit// 如果 b > 1,说明原数据并不是64位的,溢出if i == MaxVarintLen64-1 && b > 1 {return 0, -(i + 1) // overflow}return x | uint64(b)<<s, i + 1}// 将b最高位置0,加到x上x |= uint64(b&0x7f) << ss += 7}return 0, 0
}

有符号整数

较小的值(指绝对值)

对原码为1000 0000 0000 0000 0000 0000 0000 0001 的负数进行编码

负数的补码 = 除符号位外的位取反 + 1

  1. 首先计算数字的补码,负数的补码是除符号位外取反+1
1111 1111 1111 1111 1111 1111 1111 1111
  1. 按照7bit进行分组
 | 1111 | 1111111 | 1111111| 1111111 | 1111111 |
  1. 编码
|  1111111 |  1111111 |  1111111 |  1111111 | 1111 |
| 11111111 | 11111111 | 11111111 | 11111111 | 0000 1111 |

所以最终-1占了5个字节

较大的负数(只绝对值)

对原码为1111 1111 1111 0000 0000 0000 0000 0001 的负数进行编码

  1. 首先计算数字的补码,负数的补码是除符号位外取反+1
1000 0000 0000 1111 1111 1111 1111 1111
  1. 按照7bit进行分组
1000 0000000 0111111 1111111 1111111
  1. 编码
|  1111111 |  1111111 |  0111111 |  0000000 | 1000 |
| 11111111 | 11111111 | 10111111 | 10000000 | 0000 1000 |

由此可得,最终占用5个字节

Go中的实现

编码PutVarint

妙!!!

func PutVarint(buf []byte, x int64) int {// 去掉符号位,忽略符号位的影响,更方便处理ux := uint64(x) << 1// 如果x为负数,则对ux进行取反,此时最低位一定是1// 而对于正数来说,最低位始终为 0,也为解码时判断正负做了铺垫if x < 0 {ux = ^ux}// 经过上面的处理,ux 为 x 的绝对值return PutUvarint(buf, ux)
}
解码Varint
func Varint(buf []byte) (int64, int) {ux, n := Uvarint(buf) // ok to continue in presence of error// 和上面的操作是相对的,因为最低位原本不属于原数据x := int64(ux >> 1)// 如果 ux 最低位为 1,说明原数据是负数,取反if ux&1 != 0 {x = ^x}return x, n
}

总结

varint编码的思想是:

  • 对于小的数字使用更好的字节进行编码
  • 对于大的数字使用更多的字节进行编码

因为大多数时候,我们的应用程序中会大量使用小的数字,而只是少量使用大的数字,所以使用varint压缩编码,在一定程度上可以节省空间。

但是通过原始的算法思想对负数进行编码时,由于负数在计算机中存储的特殊性,所以不会起到很好的作用,所以go在实对负数进行压缩编码时,首先将负数转化为正数表示,也就是取绝对值的操作,并在解码时通过最后一位来判断原数据是正数还是负数,这样varint对负数的压缩也同样效果很好。

相关文章:

Go中varint压缩编码原理分析

文章目录 编码介绍无符号整数较小的值较大的值Go中的实现编码PutUvarint解码Uvarint 有符号整数较小的值(指绝对值)较大的负数(只绝对值)Go中的实现编码PutVarint解码Varint 总结 编码介绍 varint是一种将整数编码为变长字节的压缩编码算法&#xff0c;本篇文章就是分析该编码…...

在IDEA中如何用可视化界面操作数据库? 在idea中如何操作数据库? 在idea中如何像Navicat一样操作数据库?

1、找到database&#xff0c;创建连接 我用了中文包&#xff0c;英文状态下和我的操作完全一样 英文下第二列数据库名称为 database 2、配置相关属性&#xff0c;如IP地址&#xff0c;密码等 3、选择对应的库名&#xff0c;此处也叫架构 4、然后就可以进行愉快的操作了...

数据库安全-RedisHadoopMysql未授权访问RCE

目录 数据库安全-&Redis&Hadoop&Mysql&未授权访问&RCE定义漏洞复现Mysql-CVE-2012-2122 漏洞Hadoop-配置不当未授权三重奏&RCE 漏洞 Redis-未授权访问-Webshell&任务&密匙&RCE 等漏洞定义&#xff1a;漏洞成因漏洞危害漏洞复现Redis-未授权…...

辅助驾驶功能开发-功能规范篇(27)-3-导航式巡航辅助NCA华为

书接上回 2.2.2.3.7控制模块 控制模块由横向控制和纵向控制组成。根据横、纵向规划给出的行驶轨迹和给定速度,进行车辆的纵横向控制,输出方向盘转角、加速度或制动踏板开度和档位信息,必要条件下输出车灯信号等。 2.2.2.4 行为仲裁模块 纵向状态: 当纵向位于Off/Standby…...

探索UI设计|栅格系统的深入分析和应用

界面排版太乱了。你知道网格系统的用途吗&#xff1f;网格系统困扰着许多初级网页设计师&#xff0c;就像一个谜。如果您对网格在设计中的应用有任何疑问&#xff0c;本文是为您量身定制的&#xff0c;并深入分析UI设计中网格系统的基本要素和优点。 什么是网格系统 网格系统…...

AI 律助 Alpha GPT 线上实操发布会,重磅发布!

数字化时代,随着人工智能的迅猛发展,各行各业都在积极探索通过智能化工具实现工作效率翻升的可能性。“ ChatGPT 类产品”是未来办公应用软件发展的重要趋势之一,但如何将 ChatGPT 真正应用于法律人的工作,赋能效率提升?法律行业同样面临着新的挑战和机遇。 破局的关键是实现技…...

【漏洞复现】安全云平台存在任意文件下载getshell

漏洞描述 深圳市强鸿电子有限公司鸿运主动安全云平台存在任意文件下载漏洞,攻击者可通过此漏洞下载敏感文件信息。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权…...

【JUC】原子操作类及LongAddr源码分析

文章目录 1. 十八罗汉2. 原子类再分类2.1 基本类型原子类2.2 数组类型原子类2.3 引用类型原子类2.4 对象的属性修改原子类2.5 原子操作增强类 3. 代码演示及性能比较&#xff1a;4. LongAddr原理5. LongAddr源码分析5.1 add()5.2 longAccumulate()5.3 sum() 6. 小总结6.1 Atomi…...

203、RabbitMQ 之 使用 direct 类型的 Exchange 实现 消息路由 (RoutingKey)

目录 ★ 使用direct实现消息路由代码演示这个情况二ConstantUtil 常量工具类ConnectionUtil 连接RabbitMQ的工具类Publisher 消息生产者测试消息生产者 Consumer01 消息消费者01测试消费者结果&#xff1a; Consumer02 消息消费者02测试消费者结果&#xff1a; 完整代码&#x…...

微服务+Java+Spring Cloud +UniApp +MySql智慧工地综合管理云平台源码,SaaS模式

智慧工地围绕工程现场人、机、料、法、环及施工过程中质量、安全、进度、成本等各项数据满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效. 智慧工地综合管理云平台源码&#xff0c;PC监管端、项目端&#xff1b;APP监管端、项目端、数据可视化大屏端源码&#xf…...

QMidi Pro for Mac:打造您的专属卡拉OK体验

你是否曾经厌倦于在KTV里与朋友们争夺麦克风&#xff1f;是否想要在家中享受自定义的卡拉OK体验&#xff1f;现在&#xff0c;有了QMidi Pro for Mac&#xff0c;一切变得简单而愉快&#xff01; QMidi Pro是一款功能强大的卡拉OK播放器&#xff0c;专为Mac用户设计。它充分利…...

bindtap和catchtap的区别?

bindtap和catchtap都是小程序中用于绑定点击事件的方法。 1.bindtap的作用是绑定一个触摸事件并指定对应的处理函数。当用户点击或触摸相关元素时&#xff0c;会触发该事件&#xff0c;并执行相应的处理逻辑。 示例&#xff1a; <button bindtap"handleTap">…...

IDEA—java: 常量字符串过长问题解决

问题描述&#xff1a; Error: java: 常量字符串过长 问题分析&#xff1a; 字符串长度过长&#xff0c;导致 idea 默认使用的 javac 编译器编译不了。 解决办法&#xff1a; Javac 编译器改为 Eclipse 编译器。 File -> Settings -> Build,Execution,Deployment -&…...

云原生SIEM解决方案

云原生&#xff08;Cloud Native&#xff09;是一种基于云计算的软件开发和部署方法论&#xff0c;它强调将应用程序和服务设计为云环境下的原生应用&#xff0c;以实现高可用性、可扩展性和灵活性。 云原生的优势有哪些 高可用性&#xff1a;云原生可以实现应用程序的高可用…...

工艺边与定位孔设计经验规则总结

🏡《总目录》 目录 1,什么是工艺边和定位孔2,工艺边的设计经验原则2.1,避免尖锐角2.2,工艺边宽度设置2.3,工艺边的方向2.4,定位孔尺寸2.5,定位孔的位置3,去除工艺边的方法注意事项4,总结1,什么是工艺边和定位孔 工艺边是在SMT焊接时,为了PCB和导轨接触预留的PCB边…...

软件架构设计(业务架构、应用架构、数据架构、技术架构)

一、架构相关概念 1、系统 系统&#xff1a;由一群有关联的个体组成&#xff0c;根据某种规则运作&#xff0c;能完成个别原件不能独立完成的工作的群体。大的系统可以嵌套小系统&#xff0c;被嵌套的小系统往往称为大系统的子系统。 2、模块 模块是从逻辑上将系统分解&#…...

我们又组织了一次欧洲最大开源社区活动,Hugging Face 博客欢迎社区成员发帖、Hugging Chat 功能更新!...

每一周&#xff0c;我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新&#xff0c;包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等&#xff0c;我们将其称之为「Hugging News」。本期 Hugging News 有哪些有趣的消息&#xff0…...

学信息系统项目管理师第4版系列26_项目绩效域(下)

1. 项目工作绩效域 1.1. 涉及项目工作相关的活动和职能 1.2. 预期目标 1.2.1. 高效且有效的项目绩效 1.2.2. 适合项目和环境的项目过程 1.2.3. 干系人适当的沟通和参与 1.2.4. 对实物资源进行了有效管理 1.2.5. 对采购进行了有效管理 1.2.6. 有效处理了变更 1.2.7. 通…...

SQL sever中的索引

目录 一、索引定义 二、索引结构 2.1. B-树索引结构&#xff1a; 2.2. 哈希索引结构&#xff1a; 三、索引作用 四、索引与约束区别 五、索引级别 六、索引分类 6.1. 聚集索引&#xff08;Clustered Index&#xff09;&#xff1a; 6.2. 非聚集索引&#xff08;Noncl…...

多目标鳟海鞘算法(Multi-objective Salp Swarm Algorithm,MSSA)求解微电网优化MATLAB

一、微网系统运行优化模型 微电网优化模型介绍&#xff1a; 微电网多目标优化调度模型简介_IT猿手的博客-CSDN博客 参考文献&#xff1a; [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、多目标鳟海鞘算法MSSA 多…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...