2017-04-06 44 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 exemed'大約5M之後破裂了。如果我通過添加

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

來限制phaseTreeSet的大小,它會快速運行。爲什麼它變慢,它使用更多的內存,因此垃圾收集需要更長的時間。但每次在需要更多內存之前,都必須再次進行大量垃圾回收。顯然有相當多的內存需要,並且每次都會慢一些...

爲了加快速度,你需要把東西拿出來。也許只保留像我這樣的頂級階段,或者使用一種數據庫。

相關問題