在搜索的应用中, 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
- 大小: 65 KB
- 大小: 56.5 KB
- 大小: 56.4 KB
- 大小: 63.9 KB
- 大小: 18.8 KB
分享到:
相关推荐
**Lucene封装与性能优化详解** Lucene是一个高性能、全文本搜索库,它为开发者提供了在应用程序中实现全文检索的功能。然而,为了更好地适应实际项目需求,通常需要对其进行封装,以便于管理和提升性能。本文将深入...
在搜索引擎和大数据分析领域,Apache Lucene 是一个广泛使用的全文检索库,它提供了高效、可扩展的搜索功能。其中,Facet(分面)查询是Lucene提供的一种...理解其原理,掌握优化技巧,是提升Lucene应用性能的关键。
《lucene、lucene.NET 详细使用与优化详解》 lucene 是一个广泛使用的全文搜索引擎库,其.NET版本称为lucene.NET,它提供了强大的文本检索和分析能力,适用于各种场景下的全文搜索需求。lucene 并非一个可以直接...
本教程主要探讨的是如何利用Lucene进行索引优化,特别是通过多线程和处理多个目录来提高索引创建效率。 首先,我们需要理解Lucene的索引原理。Lucene将文档分解为词项(tokens),并对每个词项创建倒排索引。倒排...
这不仅涵盖了技术细节,还提供了实际操作建议,旨在帮助开发者针对特定场景优化其Lucene索引性能。 ### 知识点详细解析: #### 使用最新版本的Lucene 确保你正在使用Lucene的最新版本至关重要。软件的更新往往伴随...
Lucene 的优化是指对搜索引擎的性能进行优化。 Lucene 提供了多种优化方式,包括索引优化和搜索优化。 例如,下面的代码演示如何使用 Lucene 对索引进行优化: ```csharp IndexWriter writer = new IndexWriter...
本文将围绕“Lucene5学习之拼音搜索”这一主题,详细介绍其拼音搜索的实现原理和实际应用。 首先,我们需要理解拼音搜索的重要性。在中文环境中,由于汉字的复杂性,用户往往习惯于通过输入词语的拼音来寻找信息。...
"Lucene5学习之Group分组统计" 这个标题指出我们要讨论的是关于Apache Lucene 5版本中的一个特定功能——Grouping。在信息检索领域,Lucene是一个高性能、全文搜索引擎库,而Grouping是它提供的一种功能,允许用户对...
10. **性能调优**:通过分析源码,开发者可以了解到如何调整各种参数,如缓存大小、合并策略等,来优化Lucene的性能。 总的来说,深入学习Lucene 3.5.0的源码,可以帮助开发者掌握全文检索的核心技术,了解其内部...
NULL 博文链接:https://sunfish.iteye.com/blog/1415655
“Lucene5学习之排序-Sort”这个标题表明了我们要探讨的是关于Apache Lucene 5版本中的排序功能。Lucene是一个高性能、全文检索库,它提供了强大的文本搜索能力。在这个主题中,我们将深入理解如何在Lucene 5中对...
Lucene 7.1.0作为其一个重要版本,带来了许多性能优化和新特性,旨在提高搜索效率和用户体验。 1. **索引增强**:Lucene 7.1.0对索引结构进行了优化,提高了索引速度和检索性能。例如,通过改进的位集(BitSet)...
5. **性能优化**: 对内部数据结构进行了优化,提升了索引和搜索速度,降低了内存占用。 6. **倒排索引增强**: 在 3.0 版本中,引入了位向量(BitSet)技术,提高了查询效率,尤其是布尔查询。 7. **文档更新**: `...
2. 使用Filter的getDocIdSet()方法生成一个BitSet,该BitSet标记了哪些文档满足过滤条件。 3. 将Filter与Query一起传递给Searcher的search()方法,Lucene会自动使用这个Filter来过滤搜索结果。 接下来,我们来看看...
《Lucene5学习之Facet(续)》 在深入探讨Lucene5的Facet功能之前,我们先来了解一下什么是Faceting。Faceting是搜索引擎提供的一种功能,它允许用户通过分类或属性对搜索结果进行细分,帮助用户更精确地探索和理解...
Lucene搜索优化,这是从wiki上保存的
Lucene5作为其一个版本,相较于之前的版本,在性能优化和功能完善上有了显著提升。 创建索引是Lucene的核心操作之一,这个过程包括解析文档、分词、建立倒排索引等步骤。在处理大量数据时,单线程创建索引可能会...
当你调用`IndexWriter.deleteDocuments(Term term)`或`IndexWriter.deleteDocuments(Query query)`方法时,Lucene并不会立即从硬盘上删除对应的文档,而是将这些待删除的文档ID存储在一个叫做“位向量”(BitSet)的...