一段时间后BufferedReader不再缓冲了吗?

时间:2011-01-02 02:26:16

标签: java bufferedreader

抱歉,我无法发布代码,但我有一个缓冲区,其缓冲区大小为50000000字节。它可以像你期望的那样工作半小时,硬盘指示灯每两分钟闪烁一次,读取大块数据,然后在CPU处理它时再次静音。但是大约半个小时后(这是一个非常大的文件),硬盘驱动器开始颠簸,好像它一次读取一个字节。它仍处于相同的循环中,我认为我检查了自由ram以排除交换(堆大小是默认值)。

可能不会得到任何有用的答案,但值得一试。

好的我已经将堆大小更改为768mb但仍然没有。有足够的可用内存,java.exe只使用大约300mb。

现在我已对它进行了分析,并且堆保持在大约200MB,远低于可用的容量。 CPU保持在50%。然而硬盘驱动器开始疯狂地捶打。我不知道。我将用c#重写整个内容,这是我的解决方案。

这是代码(它只是一个抛弃的脚本,不是很漂亮):

    BufferedReader s = null;
    HashMap<String, Integer> allWords = new HashMap<String, Integer>();
    HashSet<String> pageWords = new HashSet<String>();
    long[] pageCount = new long[78592];
    long pages = 0;

    Scanner wordFile = new Scanner(new BufferedReader(new FileReader("allWords.txt")));
    while (wordFile.hasNext()) {
        allWords.put(wordFile.next(), Integer.parseInt(wordFile.next()));
    }
    s = new BufferedReader(new FileReader("wikipedia/enwiki-latest-pages-articles.xml"), 50000000);
    StringBuilder words = new StringBuilder();
    String nextLine = null;
    while ((nextLine = s.readLine()) != null) {
        if (a.matcher(nextLine).matches()) {
            continue;
        }
        else if (b.matcher(nextLine).matches()) {
            continue;
        }
        else if (c.matcher(nextLine).matches()) {
            continue;
        }
        else if (d.matcher(nextLine).matches()) {
            nextLine = s.readLine();
            if (e.matcher(nextLine).matches()) {
                if (f.matcher(s.readLine()).matches()) {
                    pageWords.addAll(Arrays.asList(words.toString().toLowerCase().split("[^a-zA-Z]")));
                    words.setLength(0);
                    pages++;
                    for (String word : pageWords) {
                        if (allWords.containsKey(word)) {
                            pageCount[allWords.get(word)]++;
                        }
                        else if (!word.isEmpty() && allWords.containsKey(word.substring(0, word.length() - 1))) {
                            pageCount[allWords.get(word.substring(0, word.length() - 1))]++;
                        }
                    }
                    pageWords.clear();
                }
            }
        }
        else if (g.matcher(nextLine).matches()) {
            continue;
        }
        words.append(nextLine);
        words.append(" ");
    }

6 个答案:

答案 0 :(得分:1)

您是否尝试删除缓冲区大小并使用默认值进行尝试?

答案 1 :(得分:1)

可能不是文件缓冲不起作用,而是程序占用的内存足以使虚拟内存系统页面交换到磁盘。如果尝试使用较小的缓冲区大小会发生什么?怎么样更大?

答案 2 :(得分:1)

我敢打赌,你的堆空间已经不多了而且你正在坚持退回GC。你有没有想过应用程序看看那段时间发生了什么?另外,尝试使用-verbose:gc运行以查看垃圾收集。您也可以尝试从更大的堆开始,例如“

-Xms1000m -Xmx1000m

这将为你提供1GB的堆,所以如果你全部使用它,它应该比当前发生的要晚得多。

答案 3 :(得分:1)

在我看来,如果您正在阅读的文件非常大,那么以下行可能会导致大部分文件通过StringBuilder复制到内存中。如果进程的内存占用空间过大,您可能会将垃圾收集器交换和/或抛弃。

...
words.append(nextLine);
words.append(" ");

答案 4 :(得分:0)

答案 5 :(得分:0)

在您认为Java出现问题并读取IO之前,我建议您编写一个简单的程序,它只是尽可能快地读取文件。无论文件大小如何,您都应该能够以20 MB / s或更高的速度读取文件并使用默认缓冲。您应该可以通过剥离应用程序来只读取文件来完成此操作。然后你可以自己证明阅读文件需要多长时间。

您使用了大量昂贵的操作。也许您应该看看如何使用分析器提高解析器的效率。 e.g。

word.substring(0, word.length() - 1) 

相同
word

所以第一个if子句和第二个是相同的。