为什么我的代码在处理大型数据集后会变慢?

时间:2017-04-06 08:55:33

标签: java

我有一个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 个答案:

答案 0 :(得分:0)

查看运行时行为,这显然是一个内存问题。事实上,我的测试甚至在大约500万之后就已经破了,因为GC已经超出了限制范围而且#39;在Java8上。如果我通过添加

来限制phaseTreeSet的大小
if (phaseTreeSet.size() > 100) { phaseTreeSet.pollLast(); }

它快速通过。它变慢的原因是,它使用更多的内存,因此垃圾收集需要更长的时间。但每次需要更多内存之前,它必须再次进行大量垃圾回收。显然有很多记忆要做,而且每次都慢一点......

为了加快速度,你需要让内存不足。也许只保留像我一样的顶级阶段,或使用某种数据库。