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中保存索引?
2.我用PositionFilter因爲我需要屬於一個詞的所有部分的語音標籤去到索引中的相同位置。 3.你的意思是說,擁有一個巨大的字符串在內存上比一個巨大的String []數組更好?總的來說,我不明白爲什麼有這麼多的RAM使用。我試圖強制垃圾收集,但沒有任何區別。 看起來像在Lucene內部的錯誤資源釋放。 – 2013-03-18 13:46:36
您可以隨時創建自定義Attribute,您可以通過TokenFilter添加。 Personaly我用Sentence detection matrics完成了這項工作,命名爲實體指標,並在Lucene 4之前將其序列化爲PayloadAttribute。現在,您可以創建自定義編解碼器並編寫您的索引。 – emd 2013-03-18 14:51:45
關於字符串[]的大小,這裏是解釋:64位JVM,對於一個字符串,你有16字節的對象開銷(Class,flags,lock),需要一個int字段(用於字符數)和空間用於引用表示散列的底層char數組和int,並加上填充4字節。字符反過來需要20個字節的開銷(16個對象和4個數組長度)。這涉及到40字節+ 16字節(對於空字符數組)+數組大小(在字符(2字節))+填充。僅適用於一個字符串 – emd 2013-03-18 14:58:00