私はプレーンテキストのファイルを読み込み、1行ずつ読み込み、各行をセンテンスに分割し、各センテンスを単語に分割し、1文および1文書ごとにリストに格納します。このGCオーバーヘッドの上限を超えるのはなぜですか?
は入力ファイルを5万行が含まれているので、私はIntelliJの中に私のヒープサイズは以下の通りです5005000.するのArrayListのサイズを設定:
# custom IntelliJ IDEA VM options
-Xms128m
-Xmx8192m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
私のラップトップは15G RAMを持っています。 4500000行(printステートメントで示されている)を読み取った後、非常に遅くなります。数分後、私が受け取っ:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
(一つの文書としてパース)各行が短いので、私の15Gメモリがそれを保持するのに十分以上でなければなりません。テキストファイルのサイズはわずか800MBです。 Windows 10でパフォーマンスモニタを見ているうちに、約55%のメモリしか使用されていないことが示されています。
英語ではないので、以下のコードでは「sentence.toCharArray()」を使用します。基本的には、各文字を実装の単語として扱います。
500万回線しかありませんが、なぜそれは死んでいますか?
List<List<List<String>>> allWords = new ArrayList<>(5005000);
System.out.println("Load text from file: ");
try {
BufferedReader br = Utils.fileReader(filePath);
String line;
int lineNo = 0;
while ((line = br.readLine()) != null) {
List<List<String>> wordsPerDoc = new ArrayList<>();
for (String sentence : segment(line)) {
List<String> wordsPerSentence = new ArrayList<>();
for (Character c : sentence.toCharArray()) {
wordsPerClause.add(Character.toString(c));
}
wordsPerDoc.add(wordsPerSentence);
}
allWords.add(wordsPerDoc);
lineNo++;
if(lineNo % 500000 ==0) {
System.out.println(lineNo);
}
}
System.out.println("Loaded text from file. ");
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public List<String> segment(final String line) {
List<String> sentences = new ArrayList<>();
StringTokenizer tokenizer = new StringTokenizer(line, OtherConstants.BASIC_TOKENIZATION_DELIMITER, true);
while (tokenizer.hasMoreTokens()) {
String word = tokenizer.nextToken();
sentences.add(word);
}
return sentences;
}