前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >位图bitmap的改进版:Roaring Bitmap

位图bitmap的改进版:Roaring Bitmap

原创
作者头像
cuiyi
发布2023-01-09 13:59:58
2.2K0
发布2023-01-09 13:59:58
举报

定义

咆哮位图,是一种压缩位图,是对bitmap的改进,除了使用bitmap存储数据,还使用了array等数据结构,以达到压缩的目的。

和bitmap的区别

  • 比bitmap更节省内存空间:
  1. 把32位分为2^16个容器,只为用到的容器分配空间,解决了稀疏数据浪费空间的问题。
  2. 每个容器根据数据的稠密情况使用array或bitmap数据结构,节省了每个容器占用的内存空间。
  • 比bitmap性能更高:
  1. 因为不会开辟大量不用的内存,参与计算的内存块比较少,提升计算速度。
  2. 使用有序数组保存容器,在进行逻辑运算时(与或非)基本只需要计算相同索引的容器。

作用

  • 解决bitmap统计大数据尤其是稀疏数据浪费内存空间的问题;
  • 解决bitmap内存空间无法收缩的问题:存储容器的array和ArrayContainer都是数组,支持清空和移除元素,但其空间释按照语言自身的GC机制处理。

实现原理

使用拆分模式,把2^32位拆分为2^16个容器,每个容器最多保存2^16个元素。

把要统计的数字拆分位高16位和低16位,高16位用作容器的索引、用于定位数字在哪个容器;低16位用作容器内元素的索引、用作定位数字在容器内的位置。

容器保存在一个有序数组中,在需要时被创建,不需要时不会创建。该数组名为highLowContainer。

容器有3种类型:ArrayContainer、BitmapContainer和RunContainer,根据要统计的数字的数量和数字的连续性自动选择合适的容器。

RunContainer:使用Run-Length Encoding方式压缩存储的元素,对连续数据的压缩效果特别好,但如果数据比较散列,反而会更占用空间,长度没有限制;

ArrayContainer:元素为short类型的有序数组,存储散列数据时,效果比较好;

BitmapContainer:使用bitmap存储数据,存储大量数据时,效果比较好;

容器的使用及容器之间的转换

元素数量不超过4096时,使用ArrayContainer,超过4096后使用BitmapContainer。同时,根据元素的连续性,把ArrayContainer或BitmapContaner转换为RunContainer。

ArrayContainer和BitmapContainer的选择:

元素数量不超过4096时,使用ArrayContainer;超过4096后使用BitmapContainer。

ArrayContainer使用2字节的short类型来存储每个元素,4096*2byte=8kb;BitmapContainer是定长2^16个bit,即bitmap固定大小8k。

所以当元素数量小于4096时,ArrayContainer占用的空间小于BitmapContainer;元素数量大于4096时,ArrayContainer占用的空间大于BitmapContainer;元素数量等于4096时,两者占用的空间相同,都是8kb。

ArrayContainer保证元素的有序性,使用二分查找进行读写,时间复杂度是O(logn);BitmapContainer读写时间复杂度是O(1)或O(n)。

创建:

如果是单个元素,直接使用ArrayContainer;

如果是多个连续元素,比较ArrayContainer和RunContainer占用空间的大小,选择占用空间小的;

转换:

如果当前是ArrayContainer:

元素数量大于4096时,直接在添加元素时转换为BitmapContainer;

运行runOptimize()时,比较ArrayContainer和RunContainer占用的空间,选择占用空间小的;

如果当前是BitmapContainer:

元素被删除,元素数量小于等于4096时,直接转换为ArrayContainer;

运行runOptimize()时,比较bitmapContainer和RunContainer占用的空间,选择占用空间小的;

如果当前是RunContainer:

只有运行runOptimize()时,根据当前的元素数量,同时比较三种容器占用的空间,选择占用空间小的;

ArrayContainer是同步转换,即在每个写操作中检测阈值,如果达到阈值则直接做对应的转换,先移动旧元素再添加新元素。

Roaring Bitmap不是一种常驻进程的服务,不存在后台调用的情况;在各种容器的读写操作中也没有调用runOptimize()函数。所以runOptimize()就是一个常规函数,是手动调用执行的。一旦要调用这个函数,必须有一个基本的调用策略,而不是随机的或做一次性的调用,否则可能不但达不到优化效果,还会使性能更低下。

高16位和低16位的计算

  1. 把数字转换为二进制,左补0成为4字节长度。
  2. 把左右各2字节分别直接转换为十进制,然后再根据需要把两个十进制分别转换为十六进制。
  3. 大端模式右为低位左为高位,左边的十进制/十六进制就是数组的高16位的值,右边的十进制/十六进制就是其低16位的值。

也可以理解为:使用数字对2^16的整除定位所在的容器,使用数字对2^16的模定位在容器中的位置。

使用方式

各编程语言的API;

https://www.roaringbitmap.org/

https://roaringbitmap.readthedocs.io/en/latest/index.html

统计long类型的数字

Roaring Bitmap无法统计4字节以上的数字,如64位的数字,可以使用Roaring64Bitmap或Roaring64NavigableMap。

参考推荐

https://github.com/RoaringBitmap/RoaringBitmap/tree/master/RoaringBitmap

https://zhuanlan.zhihu.com/p/445396980

https://cloud.tencent.com/developer/article/1136054

https://blog.csdn.net/tonywu1992/article/details/104746214

https://cloud.tencent.com/developer/article/1753528

https://blog.csdn.net/penriver/article/details/119736050

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义
  • 和bitmap的区别
  • 作用
  • 实现原理
  • 容器的使用及容器之间的转换
  • 高16位和低16位的计算
  • 使用方式
  • 统计long类型的数字
  • 参考推荐
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档