大数值使用BitSet存储导致的内存溢出

这篇具有很好参考价值的文章主要介绍了大数值使用BitSet存储导致的内存溢出。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景:

在日常的工作中,使用Redis的bitmap统计每天的登录用户数,使用java的BitSet进行统计总数或者与或非等操作时,我们可以看到BitSet/Redis的Bitmap操作的身影,他们也的确能减少内存的使用量以及操作的性能,但是我们不能神话这两个结构的作用,认为什么数据都适合转成用BitSet/Redis的Bitmap然后操作.

BitMap/BitSet不适用的场景:

举一个最简单的例子,保存一个Integer.max/2的正整数值,我们正常使用Int四个字节就够了,把这个整数放到Set或者List集合进行操作即可,但是有些人非要使用BitSet来存放,那么你知道仅仅存储这一个整数,BitSet需要多少字节吗?

    public static void bitSetTest() {
        BitSet bitSet = new BitSet();
        bitSet.set(Integer.MAX_VALUE / 2, true);
        System.out.println(bitSet.toByteArray().length);
    }

程序运行结果如下: 134217728, 看到没,BitSet需要将近134217728/1024/1024=130M的字节来存放这一个整数,惊讶不?同理这个结论可以推理到使用Redis的BitMap结构,那么为什么这些结构需要这么多的字节来存放仅仅一个整数?我们先大概看一下BitSet/Bitmap的存储数据结构:
大数值使用BitSet存储导致的内存溢出
可以看到所谓的bit操作只是说第一个字节可以存放8这个绝对值,第一个字节+第二个字节可以存放16这个绝对值,也就是说绝对值越大,所需要的字节数组越大,其实只有最后一个bit存放着1这个位,其他前面的字节数组都是存放0,完全被浪费掉了,不过还是需要分配这些字节数组,这就是存放Integer.MAX_VALUE /2 这样一个整数需要134M字节数组的原因。
其实从这里你可以发现类似BitSet和Redis的BitMap的结构,它占用的字节数只和要存放的数字的最大值有关,也就是说和这个BitSet存放进去多少数量没有关系,比如下面的代码:

    public static void bitSet1Test(){
        BitSet bitSet = new BitSet();
        bitSet.set(Integer.MAX_VALUE /2, true);
        for(int i=0;i<1000000;i++){
            bitSet.set(RandomUtils.nextInt(0, Integer.MAX_VALUE /2));
        }
        System.out.println(bitSet.toByteArray().length);
    }

程序运行结果如下: 134217728, 可以看到BitSet里面存放了10w个元素,不过元素的最大值是Integer.max/2,最终它占用的内存大小是134217728/1024/1024=130M,有没有发现存放1个Integer.max/2和存放10w个最大值不超过Integer.max/2的两个BitSet的内存占用是一样的?没错,就是一样的

所以我们可以得出结论: 想要高效使用BitSet和Redis的Bitmap数据结构,里面存放的数值要尽可能小,这样才能占用尽可能小的内存。

那么有人就问了,如果我的数值就是这么大呢?有办法使用BitSet和Redis的Bitmap数据结构吗?
答案是:你需要经过一层转换,也就是你需要把你这个大的整数值映射到某个小的整数值再放到BitSet/Redis的Bitmap中,等到从BitSet/Redis的Bitmap把这个小的数值取出时,再映射成原来的大的数值,这样就可以高效的使用BitSet/Redis的Bitmap结构进行操作了

彩蛋:Roaring64Bitmap/Roaring32Bitmap 和这里的BitSet/Redis的Bitmap的结论一样吗?

Roaring64Bitmap/Roaring32Bitmap和这里的BitSet/Redis的Bitmap的存储结构不一样,他们占用的内存虽然也是受到数值绝对值大小的影响,但是并没有像BitSet/Redis的Bitmap这样极端,所以使用Roaring64Bitmap和Roaring32Bitmap结构时最好首先进行测试,不过可以肯定的是,这些结构在保存大的数值时内存占用很大,和直接使用Long数组存放相差并不大,所以原则是一致的,首先把大的数值转成小的数值后再放到这些Bit数据结构中进行存储和运算.文章来源地址https://www.toymoban.com/news/detail-494744.html

到了这里,关于大数值使用BitSet存储导致的内存溢出的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用asan检测内存泄漏、堆栈溢出等问题

    操作过程参考:链接 缘起:程序在移动端崩溃,mac端复现不了,于是在写个崩溃位置函数的调用demo,使用ASAN工具进行排查。 验证过程 1、代码 main.cpp 使用附加ASAN工具的方式进行编译: 执行: 没有问题,以上是验证过程,如有问题执行时ASAN会提示有问题的相关位置。 介绍

    2024年02月11日
    浏览(60)
  • Flutter开发 键盘弹起导致底部溢出问题

            flutter版本:3.7.12         表现:登录页为从上往下Column布局,但是内容不足以撑满一整屏(约70%),键盘弹起的时候导致底部溢出,查了一下资料,都说给Scaffold加上属性 加上后确实不会再出现溢出表现,但是同时页面也没有随着键盘的弹起而弹起,导致一些小屏

    2024年01月17日
    浏览(53)
  • python中使用selenium进行爬虫时,导致(内存已缓存)备用内存占用过大导致崩溃问题,3个解决方案

    在使用python进行爬虫的时候,使用selenium进行爬取的时候经常会出现已缓存过大的情况,如果缓存出现过大之后再次执行的话就会计算机拒绝,但是这个时候我们的内存又有很多空间可以使用,一开始我以为是占用文件过多然后点360的那个进行文件整理和清理垃圾,结果效果

    2023年04月08日
    浏览(50)
  • Java中的内存泄露、内存溢出与栈溢出

    大家好,我是欧阳方超。本次就Java中几个相似而又不同的概念做一下介绍。内存泄漏、内存溢出和栈溢出都是与内存相关的问题,但它们之间有所不同。 我们经常会遇到内存泄漏、内存溢出和栈溢出等问题,这些问题都与内存的使用有关。 内存泄漏(memory leak)指的是程序

    2024年02月03日
    浏览(68)
  • 一次Python本地cache不当使用导致的内存泄露

    近期一个大版本上线后,Python编写的api主服务使用内存有较明显上升,服务重启后数小时就会触发机器的90%内存占用告警,分析后发现了本地cache不当使用导致的一个内存泄露问题,这里记录一下分析过程。 该cache大概实现代码如下: 如上述代码,该LocalCache核心在于一个存储

    2024年02月11日
    浏览(38)
  • 性能优化-内存泄漏、内存溢出、cpu占用高、死锁、栈溢出详解

    含义:内层泄露是程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费。(换言之,GC回收不了这些不再被使用的对象,这些对象的生命周期太长) 危害:当应用程序长时间连续运行时,会导致严重的性能下降;OOM;偶尔会耗尽连接对象;可

    2024年01月19日
    浏览(65)
  • 什么是内存溢出,什么是内存泄漏?

    提示:以下是本篇文章正文内容,下面案例可供参考 假设我们 JVM 中可用的内存空间只剩下 3M,但是我们要创建一个 5M 的对象,那么,新创建的对象就放不进去了。这个时候,我们就叫做内存溢出。就好比是一个容量只有 300ml 的水杯,我们硬要往里面倒500ml 的水,这时候,

    2024年02月12日
    浏览(42)
  • Android之内存泄漏与内存溢出

    内存泄漏(memory leak):是指程序在申请内存后,无法释放已申请的内存空间,导致系统无法及时回收内存并且分配给其他进程使用。通常少次数的内存无法及时回收并不会到程序造成什么影响,但是如果在内存本身就比较少获取多次导致内存无法正常回收时,就会导致内存

    2024年02月13日
    浏览(48)
  • 什么是内存溢出?什么是内存泄露?

    文章目录 一、什么是内存溢出?  二、什么是内存泄露? 三、如何避免内存溢出和内存泄露? 一、什么是内存溢出?         假设我们JVM中可用的内存空间只有 3M ,但是我们要创建一个 5M 的对象,那么新创建的对象就放不进去了。这个时候,我们就叫做内存溢出。就好

    2024年02月08日
    浏览(64)
  • 内存溢出、内存泄露的概述及常见情形

    java doc 中对 Out Of Memory Error 的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存。 JVM 提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,由于 GC(垃圾回收)一直在发展,所有一般情况下,除非应用程序占用的内存增长速度非常快,造成垃圾

    2024年01月21日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包