2013-03-18 57 views
0

我試圖做幾個文本文檔的索引。Lucene索引器在一個小文檔集合上轉出OutOfMemory

它們的內容僅僅是場製表符分隔的字符串:

WORD<\t>w1<\t>w2<\t>...<\t>wn 

POS<\t>pos1<\t>pos2_a:pos2_b:pos2_c<\t>...<\t>posn_a:posn_b 
... 

對於POS字段,':'-分隔的標記對應於相同的歧義詞。

總共有5個文件,總大小爲10 MB。 索引時,java使用大約2 GB的RAM並最終拋出一個OOM錯誤。

String join_token = tok.nextToken(); 
// atomic tokens correspond to separate parses 
String[] atomic_tokens = StringUtils.split(join_token, ':'); 
// marking each token with the parse number 
for (int token_index = 0; token_index < atomic_tokens.length; ++token_index) { 
    atomic_tokens[token_index] += String.format("|%d", token_index); 
} 
String join_token_with_payloads = StringUtils.join(atomic_tokens, " "); 
TokenStream stream = new WhitespaceTokenizer(Version.LUCENE_41, // OOM exception appears here 
              new StringReader(join_token_with_payloads)); 
// all these parses belong to the same position in the document 
stream = new PositionFilter(stream, 0); 
stream = new DelimitedPayloadTokenFilter(stream, '|', new IntegerEncoder()); 
stream.addAttribute(OffsetAttribute.class); 
stream.addAttribute(CharTermAttribute.class); 
feature = new Field(name, 
        join_token, 
        attributeFieldType); 
feature.setTokenStream(stream); 
inDocument.add(feature); 

從內存的角度來看這個代碼有什麼問題,以及如何用盡可能少的數據在RAM中保存索引?

回答

1

如果我理解的問題吧(我沒有嘗試過了)這是我的建議

  1. 它在這對java的
  2. 你不公約的代碼使用駱駝情況下很好的做法不需要手動生成位置,只需使用Field.TermVector.WITH_POSITIONS_OFFSETS創建一個字段,並且度量標準將在索引中結束。
  3. 創建如此龐大的String數組會導致非常大的內存開銷 - >使用StringBuilder。
  4. 使用LetterTokenizer來標記流或延長CharTokenizer
  5. 寫自己的標記生成器
  6. 順便說一句偉大的書Lucene in Action
+0

2.我用PositionFilter因爲我需要屬於一個詞的所有部分的語音標籤去到索引中的相同位置。 3.你的意思是說,擁有一個巨大的字符串在內存上比一個巨大的String []數組更好?總的來說,我不明白爲什麼有這麼多的RAM使用。我試圖強制垃圾收集,但沒有任何區別。 看起來像在Lucene內部的錯誤資源釋放。 – 2013-03-18 13:46:36

+1

您可以隨時創建自定義Attribute,您可以通過TokenFilter添加。 Personaly我用Sentence detection matrics完成了這項工作,命名爲實體指標,並在Lucene 4之前將其序列化爲PayloadAttribute。現在,您可以創建自定義編解碼器並編寫您的索引。 – emd 2013-03-18 14:51:45

+0

關於字符串[]的大小,這裏是解釋:64位JVM,對於一個字符串,你有16字節的對象開銷(Class,flags,lock),需要一個int字段(用於字符數)和空間用於引用表示散列的底層char數組和int,並加上填充4字節。字符反過來需要20個字節的開銷(16個對象和4個數組長度)。這涉及到40字節+ 16字節(對於空字符數組)+數組大小(在字符(2字節))+填充。僅適用於一個字符串 – emd 2013-03-18 14:58:00