通过JNI使用C ++尖叫快速进行Lucene搜索
一天結(jié)束時(shí),Lucene執(zhí)行查詢時(shí),在初始設(shè)置后,真正的熱點(diǎn)通常是相當(dāng)基本的代碼,它解碼整數(shù)docID,術(shù)語頻率和位置的順序塊,并對其進(jìn)行匹配(例如,對BooleanQuery并集或交集),則為每個(gè)匹配項(xiàng)計(jì)算得分,并在收集過程中保存具有競爭力的匹配項(xiàng)。 甚至顯然復(fù)雜的查詢(如FuzzyQuery或WildcardQuery FuzzyQuery經(jīng)過重寫過程,從而將其簡化為更簡單的形式(如BooleanQuery 。 Lucene的熱點(diǎn)非常簡單,以至于無法通過將它們移植到本地C ++(通過JNI)來對其進(jìn)行優(yōu)化!
因此,我這樣做了,創(chuàng)建了lucene-c-boost github項(xiàng)目,其結(jié)果是令人興奮的:
|
這些結(jié)果顯示在完整的,多細(xì)分的Wikipedia英語索引中,包含33.3 M個(gè)文檔。 除了令人驚訝的加速效果外,還很高興看到優(yōu)化的C ++版本的方差(StdDev列)通常較低,因?yàn)?#xff08;大部分)熱點(diǎn)已被排除在等式之外。
該API易于使用,并且可與默認(rèn)編解碼器一起使用,因此您無需嘗試重??新編制索引即可:代替IndexSearcher.search ,請調(diào)用NativeSearch.search 。 如果查詢可以優(yōu)化,它將被優(yōu)化; 否則,它將無縫地回IndexSearcher.search 。 它與Lucene完全分離,并與現(xiàn)有的Lucene 4.3.0 JAR一起使用,使用Java的反射API來獲取必要的位。
這都是非常新的代碼,我敢肯定有很多令人興奮的錯(cuò)誤,但是(在進(jìn)行一些有趣的調(diào)試之后!)使用NativeSearch.search時(shí),所有Lucene核心測試現(xiàn)在都可以通過。
這不是Lucene的C ++端口
此代碼絕對不是Lucene的常規(guī)C ++端口。 相反,它實(shí)現(xiàn)了一組非常狹窄的類,特別是常見的查詢類型。 這些實(shí)現(xiàn)不是通用的:它們硬編碼(專門化)特定代碼,刪除所有抽象,例如Scorer , DocsEnum , Collector , DocValuesProducer等。
在何時(shí)應(yīng)用優(yōu)化存在一些主要限制:
- 到目前為止僅在Linux和Intel CPU上進(jìn)行了測試
- 需要Lucene 4.3.x
- 必須將NativeMMapDirectory用作Directory實(shí)現(xiàn),該實(shí)現(xiàn)將整個(gè)文件映射到RAM(避免基于Java的MMapDirectory必須執(zhí)行的分塊)
- 必須使用默認(rèn)編解碼器
- 僅支持按分?jǐn)?shù)排序
- 沒有一個(gè)優(yōu)化的實(shí)現(xiàn)使用advance :首先,這段代碼相當(dāng)復(fù)雜,要移植到C ++會花費(fèi)很多工作;其次,受益于先進(jìn)的查詢通常已經(jīng)非常快了,因此我們最好將它們留在Java中
BooleanQuery是經(jīng)過優(yōu)化的,但是僅當(dāng)所有子句都是針對同一字段的TermQuery 。
C ++不比Java快!
無論如何,不??一定如此:在有人大聲疾呼這些結(jié)果如何“證明” Java比C ++慢得多之前,請記住,這遠(yuǎn)非“純粹的” C ++ vs Java測試。 至少有以下三個(gè)單獨(dú)的更改混合在一起:
- 算法上的變化。 例如, lucene-c-boost有時(shí)使用BooleanScorer ,其中Lucene使用BooleanScorer2 。 確實(shí),我們需要修復(fù)Lucene來進(jìn)行類似的算法更改(當(dāng)它們更快時(shí))。 特別是,在上述結(jié)果中包括Not子句以及IntNRQ所有OrXX查詢都將從算法更改中受益。
- 代碼專業(yè)化: lucene-c-boost將搜索作為大型的可怕外觀函數(shù)來實(shí)現(xiàn),從而刪除了所有不錯(cuò)的Lucene抽象。 盡管在Lucene中顯然需要抽象,但是不幸的是,它們增加了運(yùn)行時(shí)的開銷,因此刪除這些抽象會帶來一些好處。
- C ++與Java
目前尚不清楚到底是哪個(gè)部分帶來了多少收益。 實(shí)際上,我需要?jiǎng)?chuàng)建“匹配的”專用Java源代碼來進(jìn)行更純凈的測試。
此代碼很危險(xiǎn)!
具體來說,只要將本地C ++代碼嵌入Java中,我們就有Java開發(fā)人員認(rèn)為我們拋棄的C ++所有有趣的問題。 例如,如果存在錯(cuò)誤(可能是!),或者甚至是應(yīng)用程序?yàn)E用了無辜的API,例如在其他線程仍在使用IndexReader時(shí)意外關(guān)閉了IndexReader ,則該過程將遇到Segmentation Fault ,并且OS將破壞JVM。 。 可能還有內(nèi)存泄漏! 而且,是的,C ++源代碼甚至使用goto語句 。
工作正在進(jìn)行中…
這是一項(xiàng)正在進(jìn)行的工作,仍然有許多想法需要探索。 例如,Lucene的4.3.x版的默認(rèn)PostingsFormat店大端多頭,這意味著小端的Intel CPU必須做字節(jié)交換的每個(gè)帖子塊進(jìn)行解碼時(shí),這么一件事是嘗試一個(gè)PostingsFormat在搜索時(shí)CPU更好地優(yōu)化。 位置查詢,過濾器和嵌套BooleanQuery以及某些配置(例如,省略規(guī)范的字段)尚未進(jìn)行優(yōu)化。 歡迎補(bǔ)丁!
盡管如此,初步結(jié)果還是很有希望的,如果您愿意冒險(xiǎn)冒險(xiǎn)以換取大幅度提速,請稍作調(diào)整并報(bào)告。
翻譯自: https://www.javacodegeeks.com/2013/06/screaming-fast-lucene-searches-using-c-via-jni.html
總結(jié)
以上是生活随笔為你收集整理的通过JNI使用C ++尖叫快速进行Lucene搜索的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 360全景记录仪的十大排名(汽车360全
- 下一篇: 构建器模式:适用于代码,适用于测试