Фон
У меня есть пакетная программа Spring, которая читает файл (пример файла, с которым я работаю, имеет размер ~ 4 ГБ), выполняет небольшой объем обработки файла и затем записывает его в базу данных Oracle.
Моя программа использует 1 поток для чтения файла и 12 рабочих потоков для обработки и передачи базы данных.
Я перелистываю много-много-много памяти молодого поколения, из-за чего моя программа работает медленнее, чем я думаю.
Настройка
JDK 1.6.18
Пружинная партия 2.1.х
4-ядерный станок с 16 ГБ оперативной памяти
-Xmx12G
-Xms12G
-NewRatio=1
-XX:+UseParallelGC
-XX:+UseParallelOldGC
Задача
С этими параметрами JVM я получаю около 5x ГБ памяти для Tenured Generation и около 5X ГБ памяти для Young Generation.
В процессе обработки этого одного файла у меня есть постоянное поколение. Максимальный объем может достигать 3 ГБ, и мне никогда не нужно делать один полный сборщик мусора.
Однако молодое поколение достигает максимума много раз. Он достигает диапазона 5 ГБ, а затем происходит параллельный второстепенный сборщик мусора и очищает Young Gen до 500 МБ. Незначительные GC хороши и лучше, чем полноценные GC, но они все еще сильно замедляют мою программу (я почти уверен, что приложение все еще зависает, когда происходит сбор молодого поколения, потому что я вижу, что активность базы данных прекращается). Я трачу более 5% времени моей программы, замороженной для второстепенных групп, и это кажется чрезмерным. Я бы сказал, в ходе обработки этого файла 4 ГБ, я перетаскиваю 50-60 ГБ памяти молодого поколения .
Я не вижу явных недостатков в моей программе. Я пытаюсь подчиняться общим принципам ОО и писать чистый Java-код. Я пытаюсь не создавать объекты без причины. Я использую пулы потоков и, по возможности, передаю объекты вместо создания новых объектов. Я собираюсь начать профилирование приложения, но Мне было интересно, есть ли у кого-нибудь хорошие общие правила или анти-паттерны, чтобы избежать этого, что приведет к чрезмерному оттоку памяти ? Является ли 50-60 ГБ оттока памяти для обработки файла 4 ГБ лучшим, что я могу сделать? Должен ли я вернуться к трюкам JDk 1.2, таким как Object Pooling? (хотя Брайан Гетц выступил с докладом, в котором говорилось о том, почему объединение объектов глупо, и нам больше не нужно это делать. Я доверяю ему гораздо больше, чем себе… :))