2017-04-06 5 views
-2

私は基本的にファイルを行単位で読み込んでその行をセットに格納するJavaプログラムを持っています。ファイルには30000000以上の行が含まれています。私のプログラムは最初は速く走っていますが、20000000行を処理した後には遅くなり、待ち時間も遅くなります。誰かがなぜこのようなことが起こるのかを説明することができます。どうすればプログラムを高速化できますか?大きなデータセットを処理した後にコードが遅くなるのはなぜですか?

ありがとうございました。

public void returnTop100Phases() { 
    Set<Phase> phaseTreeSet = new TreeSet<>(new Comparator<Phase>() { 
     @Override 
     public int compare(Phase o1, Phase o2) { 
      int diff = o2.count - o1.count; 
      if (diff == 0) { 
       return o1.phase.compareTo(o2.phase); 
      } else { 
       return diff > 0 ? 1 : -1; 
      } 
     } 
    }); 
    try { 
     int lineCount = 0; 
     BufferedReader br = new BufferedReader(
       new InputStreamReader(new FileInputStream(new File("output")), StandardCharsets.UTF_8)); 
     String line = null; 
     while ((line = br.readLine()) != null) { 
      lineCount++; 
      if (lineCount % 10000 == 0) { 
       System.out.println(lineCount); 
      } 
      String[] tokens = line.split("\\t"); 
      phaseTreeSet.add(new Phase(tokens[0], Integer.parseInt(tokens[1]))); 
     } 
     br.close(); 
     PrintStream out = new PrintStream(System.out, true, "UTF-8"); 
     Iterator<Phase> iterator = phaseTreeSet.iterator(); 
     int n = 100; 
     while (n > 0 && iterator.hasNext()) { 
      Phase phase = iterator.next(); 
      out.print(phase.phase + "\t" + phase.count + "\n"); 
      n--; 
     } 
     out.close(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
+1

コードはどうですか?行単位で読み込む方法を使用し、大きすぎる場合はファイル全体をメモリに格納しないでください。最終的にガベージコレクションがアプリケーションコードより多くなることがあります。 – Eugene

+1

あなたのコードは "各行に対して、前のすべての行に対してチェックする"のような何かをしていますか? –

+0

TreeSetに追加する項目が多いほど、新しい項目を挿入するときに比較を実行する必要があります。あなたが約3000万アイテムを話しているときに「遅い」となることは驚くべきことではありません。 – f1sh

答えて

0

これは明らかにメモリの問題です。実際、私のテストは、Java8で 'GC overhaed limit exeeded'を約5M後に壊してしまった。 phaseTreeSetのサイズを制限すると、

if (phaseTreeSet.size() > 100) { phaseTreeSet.pollLast(); } 

が素早く実行されます。なぜそれが遅くなるのかということは、より多くのメモリを使用するため、ガーベジコレクションに時間がかかります。しかし、より多くのメモリが必要になるたびに、大きなガベージコレクションを再度実行する必要があります。明らかに、かなりのメモリがあり、少し遅くなる度に...

メモリを使い切る必要がある場合は、高速化する必要があります。たぶん、私がやったようなトップフェーズだけを保つか、あるいはデータベースの種類を使うことによって。

関連する問題