Производительность BufferedReader и FileReader read () - большой текстовый файл

Я использую следующие 2 кода для чтения большого файла.

Это с использованием FileReader:

File file = new File("/Users/Desktop/shakes.txt");
FileReader reader = new FileReader(file);

int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    System.out.print((char) ch);
}
long end = System.currentTimeMillis();

И следующее при использовании BufferedReader:

File file = new File("/Users/Desktop/shakes.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));

int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    System.out.print((char) ch);
}
long end = System.currentTimeMillis();

Исходя из документации для BufferedReader:

It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.

Учитывая эту документацию и размер буфера по умолчанию 8192 класса BufferedReader, не должно ли общее время чтения файла с помощью BufferedReader быть быстрее? В настоящее время оба фрагмента кода выполняются на моей машине за ~ 3000 мс. Однако, если я использую readLine в BufferedReader, производительность существенно улучшается (~ 200 мс).

Мысли о чем-то, чего мне не хватает? Разве не ожидается, что даже при использовании метода read () BufferedReader должен работать лучше, чем чтение из FileReader?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
494
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Использование BufferedReader действительно быстрее, чем использование только FileReader.

Я выполнил ваш код на своей машине со следующим текстовым файлом https://norvig.com/big.txt (6 МБ).

  • Первоначальный результат показывает примерно то же время. По 17 секунд каждый.
  • Однако это связано с тем, что System.out.print() является узким местом (внутри цикла). Без печати результат в 4 раза быстрее с BufferedReader. 200 мс против 50 мс. (Сравните это с 17 секундами раньше)

Другими словами, не используйте System.out.print() при тестировании.

Пример

Улучшенный тест может выглядеть так, используя StringBuilder.

File file = new File("/Users/Desktop/shakes.txt");
FileReader reader = new FileReader(file);

int ch;
StringBuilder sb = new StringBuilder();
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    //System.out.print((char) ch);
    sb.append((char) ch);
}
long end = System.currentTimeMillis();

System.out.println(sb);

Приведенный выше код обеспечивает тот же результат, но работает намного быстрее. Он точно покажет разницу в скорости при использовании BufferedReader.

Спасибо за ответ, J.A.P! Я изменил свой код, чтобы избавиться от System.out, и BufferedReader действительно лучше, чем FileReader, и каждый раз почти на один и тот же фактор.

vksinghh 23.12.2018 14:17

Thoughts on something that I'm missing?

Должно быть быстрее читать файл по символу за раз с BufferedReader, чем с FileReader. (На порядки!) Так что я подозреваю, что проблема в ваших тестах.

  1. Ваш тест измеряет как чтение файла, так и его запись в стандартный вывод. Таким образом, ваши показатели производительности будут искажены накладными расходами письмо файла. И если ваш вывод записывается на «консоль», то эти накладные расходы включают накладные расходы на рисование символов на экране ... и прокрутку.

  2. Ваш тест не учитывает накладные расходы на запуск виртуальной машины.

  3. Ваш тест (очевидно) не влияет на кеширование файлов. (При первом чтении файла он будет считан с диска. Если вы прочитаете его снова вскоре после этого, вы будете читать мая из копии файла, кэшированного в памяти операционной системой. Это будет быстрее.)

Спасибо, Стивен. Вы правы, и мне также удалось это проверить, удалив операторы System.out.

vksinghh 23.12.2018 14:19

Другие вопросы по теме