LevelDB内部通过采用变长编码,对数据进行压缩来减少存储空间,采用CRC进行数据正确性校验。下面就对varint编码进行学习。

传统的integer是以32位来表示的,存储需要4个字节,当如果整数大小在256以内,那么只需要用一个字节就可以存储这个整数,这样就可以节省3个字节的存储空间,Google varint就是根据这种思想来序列化整数的

无符号

Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。

Varint 中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,会用两个字节。

例如整数1的表示,仅需一个字节:

0000 0001

例如300的表示,需要两个字节:

1010 1100 0000 0010

采用 Varint,对于很小的 int32 类型的数字,则可以用 1 个 byte 来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法,大的数字则需要 5 个 byte 来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息。

下图演示了 Google Protocol Buffer 如何解析两个 bytes。注意到最终计算前将两个 byte 的位置相互交换过一次,这是因为 Google Protocol Buffer 字节序采用 little-endian 的方式。

有符号

如果使用int32/int64表示一个负数,该字段的值无论是-1还是-2147483648,其编码后长度将始终为10个字节,就如同对待一个很大的无符号整型一样。反之,如果使用的是sint32/sint64,Protocol Buffer将会采用ZigZag编码方式,其编码后的结果将会更加高效。
这里简单讲述一下ZigZag编码,该编码会将有符号整型映射为无符号整型,以便绝对值较小的负数仍然可以有较小的varint编码值,如-1。下面是ZigZag对照表:

其公式为:
(n << 1) ^ (n >> 31) //sint32
(n << 1> ^ (n >> 63) //sint64
需要补充说明的是,Protocol Buffer在实现上述位移操作时均采用的算术位移,因此对于(n >> 31)和(n >> 63)而言,如果n为负值位移后的结果就是-1,否则就是0。
注:简单解释一下C语言中的算术位移和逻辑位移。他们的左移操作都是相同的,即低位补0,高位直接移除。不同的是右移操作,逻辑位移比较简单,高位全部补0。而算术位移则需要视当前值的符号位而定,补进的位和符号位相同,即正数全补0,负数全补1。换句话说,算术位移右移时要保证符号位的一致性。在C语言中,如果使用 int变量位移时就是算术位移,uint变量位移时是逻辑位移。

实现可以参考下面文章

http://www.searchtb.com/2013/04/google-group-varint-compression-high-efficient-implementation.html?spm=0.0.0.0.SazYq9

Varint编码的更多相关文章

  1. LevelDB 源码解析之 Varint 编码

    GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区: https://bbs.huaweicloud.com/ ...

  2. Protocol Buffers编码详解,例子,图解

    Protocol Buffers编码详解,例子,图解 本文不是让你掌握protobuf的使用,而是以超级细致的例子的方式分析protobuf的编码设计.通过此文你可以了解protobuf的数据压缩能力 ...

  3. Varint code

    Varint编码   LevelDB内部通过采用变长编码,对数据进行压缩来减少存储空间,采用CRC进行数据正确性校验.下面就对varint编码进行学习. 传统的integer是以32位来表示的,存储需 ...

  4. Protocol Buffers(2):编码与解码

    目录 Message Structure 解码代码一窥 varint Protobuf中的整数和浮点数 Length-delimited相关类型 小结 参考 博客:blog.shinelee.me | ...

  5. protocol buffer 编码

    protocol buffer能够跨平台提供轻量的序列化和反序列化,得益于其平台无关的编码格式,本文就介绍下其中的编码格式. Varints 在protocol buffer中大量使用到了Varint ...

  6. protobuf编码

     proto2 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化,适合做数据存储或 RPC 数据交换格式.可用于通讯协议.数据存储等领域的语言无关.平台无 ...

  7. Proto3:编码

    本文介绍protocol buffer消息二进制传输格式.在应用程序中使用protocol buffer时,你并不需要了解这些,但它对你了解protocol buffer格式如何影响你的编码消息的大小 ...

  8. google protocol buffer——protobuf的编码原理二

    这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们主要通 ...

  9. Base 128 Varints 编码(压缩算法)

    Base 128 Varint可以说是一种编码方式,也可以说是一种压缩算法.这种压缩算法是用来压缩数字的传输的,压缩的依据是基于一个现实:越小的数字,越经常使用 我们来看看一个例子: 如果我们要网络传 ...

随机推荐

  1. 判断DataTable是否为空

    DataTable: ) { //为空的操作 } DataRow: if(!DataRow.IsNull("列名")) { //不为空的操作 }

  2. Regional Changchun Online--Elven Postman(裸排序二叉树)

    Elven Postman Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Tot ...

  3. UI_RD协作开发流程

    1. 背景 由于android端需要进行多屏幕适配,这就给UI&RD之间的沟通产生了一些困难.我下面将会对这两种角色的沟通,说明了一下我们项目中沟通的方式和规则. 原则:客户端跟UI约定了各种 ...

  4. Centos安装软件小结-20160325

    三种安装包 bin包 rpm包 源码包 1.bin包 1.先赋予权限: chmod 777 *.bin 2.开始安装: ./.bin 2.rpm包(以jdk为例)\ yum search jdk\ y ...

  5. Redis集群创建报错

    Redis集群环境:och163/och164/och165 在执行如下脚本时报错: ./src/redis-trib.rb create 10.1.253.163: 10.1.253.164: 10 ...

  6. Spark Standalone模式伪分布式环境搭建

    前提:安装好jdk1.7,hadoop 安装步骤: 1.安装scala 下载地址:http://www.scala-lang.org/download/ 配置环境变量: export SCALA_HO ...

  7. Android开发-API指南-Fragment

    Fragments 英文原文:http://developer.android.com/guide/components/fragments.html 采集日期:2014-12-31 在本文中 设计理 ...

  8. [AFUI]App Framework Plugins

    ---------------------------------------------------------------------------------------------------- ...

  9. phpexcel 导入导出

    导出excel /** * 以下是使用示例,对于以 //// 开头的行是不同的可选方式,请根据实际需要 * 打开对应行的注释. * 如果使用 Excel5 ,输出的内容应该是GBK编码. */ //r ...

  10. cocos2dx 内存管理机制

    持续更新吧. 刚开始看了一些. 一,CCObject  提供引用计数 1,unsinged int m_uReference; //此为CCOBject的引用计数,初始化为 1: new CCObje ...