Низкая производительность с BufferedReader - PullRequest
6 голосов
/ 24 августа 2011

Я обрабатываю несколько текстовых файлов построчно, используя BufferReader.readlLine().

Два файла имеют одинаковый размер 130 МБ, но один обрабатывается за 40 секунд, а другой занимает 75 секунд.

Я заметил, что в одном файле 1,8 миллиона строк, а в другом - 2,1 миллиона.Но когда я попытался обработать файл с 3,0 миллионами строк одинакового размера, это заняло 30 минут.

Поэтому мой вопрос:

  1. Это поведение из-завремя поиска буфера чтения (я хочу знать, как BufferedReader работает или анализирует файл строка за строкой?)

  2. Есть ли способ прочитать файл строка за строкой вболее быстрый путь?

Хорошо, друзья, я предоставляю некоторые подробности.

Я разделяю строку на три части, используя регулярное выражение, а затем SimpleUnsortedWriter (предоставленоКассандра) Я записываю его в какой-то файл в виде ключа, столбца и значения.После обработки данных размером 16 МБ они сбрасываются на диск.

Но логика обработки одинакова для всех файлов, даже один файл размером 330 МБ, но без строк, около 1 миллиона, обрабатывается в течение 30 секунд.В чем может быть причина?

deviceWriter = new SSTableSimpleUnsortedWriter(
        directory,
        keyspace,
        "Devices",
        UTF8Type.instance,
        null,
        16);

Pattern pattern = Pattern.compile("[\\[,\\]]");
while ((line = br.readLine()) != null)          
{
    //split the line i n row column and value
    long timestamp = System.currentTimeMillis() * 1000;
    deviceWriter .newRow(bytes(rowKey));
    deviceWriter .addColumn(bytes(colmName), bytes(value), timestamp);

}

Изменились -Xmx256M to -Xmx 1024M, но это никак не помогает.

Обновление: По моим наблюдениям, когда я пишув буфер (в физической памяти), как нет.Количество записей в буфер увеличивается, новые записи занимают время.(Это мое предположение)

Пожалуйста, ответьте.

Ответы [ 4 ]

6 голосов
/ 24 августа 2011

Единственное, что BufferedReader делает, это читает из базового Reader во внутренний char[] буфер с размером по умолчанию 8 КБ, и все методы работают с этим буфером до его исчерпания, после чего еще 8 КБ (или что угодно) читается из базового Reader. readLine() вроде как прикреплено.

Правильное использование BufferedReader должно определенно , а не привести к увеличению времени пробега с 40 секунд на линиях 1,8 м до 30 минут на линиях 3 м. Там должно быть что-то не так с вашим кодом. Покажите это нам.

Другая возможность состоит в том, что вашей JVM не хватает памяти кучи, и она тратит большую часть 30 минут на сборку мусора, потому что ее куча заполнена на 99%, и в итоге вы получите OutOfMemoryError с большим вводом. Что вы делаете с обработанными вами строками? Они хранятся в памяти? Имеет ли значение выполнение программы с параметром командной строки -Xmx 1024M? 1015 *

1 голос
/ 24 августа 2011

BufferedReader, вероятно, не является причиной вашей проблемы с производительностью.

Судя по приведенным цифрам, в вашем коде возникает квадратичная сложность. Например, для каждой прочитанной строки вы пересматриваете каждую прочитанную ранее строку. Я просто размышляю здесь, но типичным примером проблемы может быть использование структуры данных списка и проверка, соответствует ли новая строка любым предыдущим строкам.

1 голос
/ 24 августа 2011

Посмотрите на NIO Buffered, поскольку они более оптимизированы, чем BufferReader.

Фрагмент кода с другого форума. http://www.velocityreviews.com/forums/t719006-bufferedreader-vs-nio-buffer.html

FileChannel fc = new FileInputStream("File.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
fc.read(buffer);

Редактировать: Также смотрите в этой теме Чтение больших файлов на Java

1 голос
/ 24 августа 2011

BufferedReader не будет искать, он просто кэширует символы до тех пор, пока не будет найдена новая строка, и возвращает строку в виде строки, отбрасывая (повторно используя) буфер после каждой строки. Вот почему вы можете использовать его с любым потоком или другим устройством чтения, даже с теми, которые не поддерживают поиск.

Таким образом, количество строк само по себе не должно создавать такой большой разницы на уровне читателя. Однако очень длинная строка может создать очень большую строку и выделение большого объема ОЗУ, но, похоже, это не ваш случай (в этом случае, вероятно, возникнет исключение OutOfMemory из-за превышения времени GC или аналогичного).

Насколько я вижу в вашем коде, вы не делаете ничего плохого. Я полагаю, что вы достигли какого-то предела, так как он, кажется, не является ОЗУ, может быть, это как-то связано с каким-то жестким ограничением на стороне Кассандры? Вы пытались закомментировать часть, которая пишет о Кассандре? просто чтобы посмотреть, является ли это вашей стороной или стороной Кассандры, которая вызывает проблему.

...