Извините, я не могу отправить код, но у меня есть буферизатор с 50000000 байт, заданный как размер буфера. Он работает так, как вы ожидали бы на полчаса, индикатор жесткого диска мигает каждые две минуты или около того, читая большой кусок данных, а затем снова затихает, когда процессор обрабатывает его. Но примерно через полчаса (это очень большой файл) жесткий диск начинает биться, как будто он читает по одному байту за раз. Он по-прежнему находится в одном цикле, и я думаю, что я проверил свободный баран, чтобы исключить замену (размер кучи по умолчанию).BufferedReader больше не буферизует через некоторое время?
Наверное, не получится получить полезные ответы, но стоит попробовать.
OK Я изменил размер кучи до 768mb и все еще ничего. Существует много свободной памяти, и java.exe использует только около 300 Мб.
Теперь я профилировал его и кучу осталось около 200 МБ, что значительно ниже того, что доступно. Процессор остается на уровне 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(" ");
}
Мне любопытно: для чего вам нужно использовать буферизованный считыватель с буфером на 50 МБ? Похоже, что это противоречит целям дизайна всей реализации Reader (которая сосредоточена на извлечении данных при ее анализе вместо того, чтобы читать весь файл ...). Лучше всего сосредоточиться на дизайне здесь ... –
err, потому что чтение в больших количествах данных в одно время более эффективно, чем чтение в меньших количествах из-за уменьшения системных вызовов и уменьшения в голове жесткого диска, чтобы переместить себя и т. Д. и т. д. – BobTurbo
Думаю, вы взяли в целом хороший совет и довели его до крайности. Этот совет может относиться к размеру буфера приложений размером 64k вместо 256 байтов или что-то в этом роде, но я, вероятно, не пойду намного больше. В любом случае ОС будет делать дополнительную буферизацию для вас, особенно для чтения файла последовательно. Создание собственного буфера приложений 50 мегабайт может быть в конечном счете контрпродуктивным, потому что вы можете использовать эту память для чего-то более значимого (и, по сути, это похоже на вас). –