Снижение пропускной способности ввода / вывода Java-файлов - PullRequest
3 голосов
/ 07 июля 2010

У меня есть программа, в которой каждый поток читает из файла много строк за раз, обрабатывает строки и записывает строки в другой файл.Четыре потока разделяют список файлов для обработки среди них.У меня возникают странные проблемы с производительностью в двух случаях:

  • Четыре файла по 50000 строк в каждом
    • Пропускная способность начинается при обработке 700 строк / сек, снижается до ~ 100 строк / сек
  • 30 000 файлов по 12 строк в каждом
    • Пропускная способность начинается около 800 строк / сек и остается постоянной

Это внутреннееПрограммное обеспечение, над которым я работаю, поэтому, к сожалению, я не могу поделиться исходным кодом, но основные шаги программы:

  1. Разделение списка файлов по четырем рабочим потокам
  2. Пусквсе потоки.
  3. Поток считывает до 100 строк одновременно и сохраняет в массиве String[].
  4. Поток применяет преобразование ко всем строкам в массиве.
  5. Поток записывает строки вфайл (не совпадает с входным файлом).
  6. 3-5 повторяется для каждого потока, пока все файлы не будут полностью обработаны.

Чего я не понимаю, так это почему 30 тысяч файлов с 12каждая строка дает мне большую производительность, чем несколько файлов с человекому строк каждая.Я ожидал бы, что накладные расходы на открытие и закрытие файлов будут больше, чем на чтение одного файла.Кроме того, снижение производительности в первом случае носит экспоненциальный характер.

Я установил максимальный размер кучи равным 1024 МБ, и, похоже, он использует максимум 100 МБ, поэтому перегруженный GC неэта проблема.У вас есть другие идеи?

Ответы [ 6 ]

3 голосов
/ 07 июля 2010

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

При работе с одним стандартным диском последовательный ввод-вывод обычно лучше параллельного ввода-вывода.

2 голосов
/ 07 июля 2010

Я предполагаю, что файлы расположены на одном и том же диске, и в этом случае вы, вероятно, перегружаете диск (или делаете недействительным кэш диска \ ОС) несколькими потоками, пытающимися одновременно считывать и записывать.Лучшим шаблоном может быть выделение потока чтения / записи для обработки ввода-вывода, а затем изменение шаблона так, чтобы задача преобразования (что звучит дорого) выполнялась несколькими потоками.Ваш поток ввода-вывода может извлекать и перекрывать запись с операциями преобразования, когда результаты становятся доступными.Это должно остановить перегрузку диска и сбалансировать сторону ввода-вывода и ЦП вашего шаблона.

1 голос
/ 07 июля 2010

Скорее всего, ваш поток слишком долго держится за буферизованные строки [].Несмотря на то, что ваша куча намного больше, чем нужно, пропускная способность может пострадать из-за сборки мусора.Посмотрите, как долго вы держитесь за эти ссылки.

Вы также можете подождать, пока виртуальная машина не выделит больше памяти - запрос Xmx1024m не выделяет столько сразу, он захватывает то, что нужно, так как больше памятитребуется.Вы также можете попробовать -Xms1024m -Xmx1024m (т.е. выделить всю память при запуске), чтобы проверить, так ли это.

1 голос
/ 07 июля 2010

Вы пробовали запустить профилировщик Java?Это укажет, какие части вашего кода работают медленнее всего.Из этого обсуждения кажется, что Netbeans profiler - хороший вариант для проверки.

0 голосов
/ 08 июля 2010

Я бы пересмотрел этот процесс.Если вы используете BufferedReader и BufferedWriter, нет смысла читать и обрабатывать 100 строк одновременно.Это просто добавленное усложнение и еще один источник потенциальной ошибки.Делайте это по одному и упростите свою жизнь.

0 голосов
/ 07 июля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...