У меня есть программа, которая создает файл размером около 50 МБ.Во время процесса программа часто перезаписывает разделы файла и принудительно вносит изменения на диск (порядка 100 раз).Он использует FileChannel и прямые ByteBuffers через fc.read (...), fc.write (...) и fc.force (...).
Новый текст:
Теперь у меня есть лучшее представление о проблеме.Кажется, проблема в том, что я использую три разных JVM для изменения файла (один создает его, два других (запускаются с первого) записывают в него).Каждая JVM правильно закрывает файл перед запуском следующей JVM.Проблема заключается в том, что стоимость fc.write () для этого файла иногда поднимается вверх для третьей JVM (в 100 раз больше обычной стоимости).То есть все операции записи выполняются одинаково медленно, а не просто очень длинные.Интересно, что один из способов помочь этому - вставить задержки (2 секунды) между запуском JVM.Без задержки, запись всегда медленная, с задержкой, запись идет примерно каждый второй раз или около того.
Я также нашел это Stackoverflow: Как удалить файл из памяти, отображенной с помощью FileChannel в Java?, которая описывает проблему для сопоставленных файлов, которую я не использую.
То, что я подозреваю, может происходить: Java не полностью освобождает дескриптор файла, когда я вызываю close ().Когда запускается следующая JVM, Java (или Windows) распознает параллельный доступ к этому файлу и устанавливает для него дорогой обработчик параллелизма, что делает запись дорогой.Имеет ли это смысл?
Проблема возникает в Windows 7 (Java 6 и 7, протестирована на двух машинах), но не в Linux (SuSE 11.3 64).
Старый текст:
Проблема: Запуск программы из тестового набора JUnit из Eclipse или из консоли работает нормально, это занимает около 3 секунд.Запуск программы с помощью задачи ant (или с помощью JUnit, запускающего отдельную JVM с использованием ProcessBuilder) замедляет программу до 70-80 секунд для той же задачи (фактор 20-30).
Использование -Xprof показывает, что использование 'force0' и 'pwrite' проходит через крышу с 34,1% (76 + 20 тиков) до 97,3% (3587 + 2913 + 751 тиков): Быстрый запуск:
27.0% 0 + 76 sun.nio.ch.FileChannelImpl.force0
7.1% 0 + 20 sun.nio.ch.FileDispatcher.pwrite0
[..]
Медленный прогон:
Interpreted + native Method
48.1% 0 + 3587 sun.nio.ch.FileDispatcher.pwrite0
39.1% 0 + 2913 sun.nio.ch.FileChannelImpl.force0
[..]
Stub + native Method
10.1% 0 + 751 sun.nio.ch.FileDispatcher.pwrite0
[..]
ГХ и компиляция пренебрежимо малы.
Больше фактов:
Никакие другие методы не показывают существенного изменения в-Xprof output.
- Это либо быстро, либо очень медленно, ничего между ними не бывает.
- Память не проблема, все тестовые машины имеют по крайней мере 8 ГБ, процесс использует <200MB </li>
- перезагрузка компьютера не помогает
- переключение антивирусных сканеров и подобных вещей не влияет
- Когда процесс идет медленно, загрузка процессора практически не происходит
- Это никогда медленно при запуске из обычной JVM
- Это довольно стабильно медленно при запуске в JVM, которая была запущена из первой JVM (через ProcessBuilder или какant-task)
- Все JVM одинаковы.Я вывожу System.getProperty ("java.home") и параметры JVM через RuntimeMXBean RuntimemxBean = ManagementFactory.getRuntimeMXBean ();Аргументы списка = RuntimemxBean.getInputArguments ();
- Я тестировал его на двух машинах с Windows7 64-битной, Java 7u2, Java 6u26 и JRockit, аппаратное обеспечение машин отличается, но результаты очень похожи.
- Я также тестировал его из-за пределов Eclipse (муравей командной строки), но без разницы.
- Вся программа написана мной самостоятельно, все, что она делает, это чтение и запись в / из этого файла,другие библиотеки не используются, особенно нативные.-
И некоторые страшные факты, в которые я просто не верю, имеют смысл:
- Удаление всех файлов классов и перестройка проекта иногда (редко) помогают.Программа (вложенная версия) запускается быстро один или два раза, а затем снова становится очень медленной.
- Установка новой JVM всегда помогает (каждый раз!), Так что (вложенная) программа работает быстро хотя бы один раз!Установка JDK считается двумя, потому что JDK-jre и JRE-jre работают как минимум один раз.Переустановка JVM не помогает.Ни одна не делает перезагрузку.Я еще не пробовал удалять / перезагружать / переустанавливать ...
- Это единственный из двух способов, которым мне удалось получить быстрое время выполнения программы для вложенной программы.
- Что может вызвать падение производительности для вложенных JVM?
- Что именно делают эти методы (pwrite0 / force0)?-