Lucene性能优化之Bitset的误区

  在搜索的应用中, bitset 的应用相当广泛,而且是 java util 包下面标准的类,很多人也会首先使用,一般都用于记录对应的 document id 有没有选中,除了这一个解决方案,还有通过 new  数组[] 这样子的方式去记录,其实道理都大同小异,都是通过数组的下标确定对应的 document id 有没有选中。

 

  BitSet性能其实不够好

  功能差别上基本相似,但问题是性能方面如何?对于搜索应用,速度是搜索应用的生命,特别在大数据方面。我们不妨对此做一个测试,一个 bitset为1000W 的数组,遍历 10次
        
          10次的总时间约 1.1秒,平均一次就是 0.11,这个速度能接受吗?显然不能接受,平均一个搜索应用也就 0.2 ~ 0.3 秒的时间,普通一个 bitset 就吃掉了 0.1 秒,这能接受吗?
    让我们分析一下到底 bitset 的性能耗用在哪里?
   通过分析 bitset 的源码可以清楚看到,所谓的 bitset 其实就是 long 数组,某一个值都需要除以 long 类型的64位,同时还要计算具体是 long 值的第几个 bit,通过位移来实现 ,这样子做好处就是可以节省存储的空间,简单来说,如果我有一个 64 个 document id 需要保存,则只需要 new long[0] , 就可以了,仅一个 long 值,各路大神估计也很明白其中的意思,我就不再啰嗦了。
          理论上这是很快的,但得出的结论却不快,原因其实也很简单,由于在计算具体 每一个doc id 会落在数组中哪个 long 的第几个 bit ,需要2次 取余的运算,这一个就是问题的根本所有,不起眼的运算导致了速变慢了很多。具体大家可以写代码验证一下。
          各数组类型的速度比较
   为了不进行任何的除法或者取余的运算,我们可以使用最简单的方法,直接使用普通的数组
   1. 使用 int 数组,一个int占用 4个字节
                         
                      这样变成了纯通过数组下标操作了,速度快了不小,同样的条件,10次一共用了 0.5秒,平均一次 0.05 秒,约 50毫秒。从中可以看到,因为数组决定了这些在内存中是一排连续的地址,所以速度上提升非常明显!或者你现在也会想到,用 int 太浪费了,用其他更小的类型会怎么样?
    2. 使用 char 类型的,占用两个字节
      
         同样的道理,这次发现,同样的操作,换成 char 类型数组,则变成 0.31秒,平均每次 30毫秒,按这样子道理,如果换成 byte 类型,那应该是最快的
    3. 使用 byte 类别,一个byte 就是一个字节
            
              事实的确如此,这次同样条件,换成 byte 后,10次运算下来共 0.2 秒,每次约 20 毫秒,这样的速度比之前使用 bitset 的单次 0.1 秒,快了5倍了!
     结论:
     一个各种类型的对应表
              
     可以看到,其实 bitset 反而最慢,主要是因为在 bitset 里面每一次都需要做大量的取余,除法等运算,如果一两次的运算倒无影响,但进行了1000W次的运算性能损失很可观。
     Bitset 是 java 包中提供的工具类,很多人也会使用它,因为它提供了很多丰富的方法,比如取出已选中的值,统计有多少被选中等,对于普通的数组,还需要自己去实现,但我认为不是一个很大问题。
     同样的 1000W数组中, bitset 大约只用了 1000w / 64 = 150w 左右的 long 数组,空间上的确比最小的 byte 数组还要小 8 倍,但需要注意的是,在遍历的速度上 byte 数组速度上明显快不小,而且,使用完数组后, GC 也会回收,内存上的使用,我认为问题不大。
     最后,再有一点要说明的是,我们的10次测试中,每一次都会重新 new 了 1000W 的数组,假如我们 不把 new 1000W 的数组放到计时里面,就单纯看遍历数组,遍历速度将还会提升一倍!但考滤到, 使用旧的数组还有一个数组清零的过程,时间花费上也跟 new 一个 数组差不多,所以就图方便,直接每次 new  一个数组  酷 
                    by  kernaling.wong @ 2014.01.22
                                                                   欢迎转载,请注明来源  http://kernaling-wong.iteye.com/blog/2007882
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值