Гигантская виртуальная память в Java при отслеживании файлов

Я создал программу, которая работает как "tail -f" на нескольких файлах журналов на машине, используя Apache Tailer из commons IO. По сути, он запускается в потоке, открывает файл как RandomAccessFile, проверяет его длину, стремится к концу и т. Д. Он отправляет все собранные строки журнала клиенту.

Несколько неудобно то, что в Linux он может показывать огромный объем памяти VIRT. Прямо сейчас он говорит 16,1 г ВИРТ (!!) и 203 м RES.

Я немного прочитал о виртуальной памяти и понял, что часто "не о чем беспокоиться". Но все же, 16 ГБ? Это действительно здорово?

Когда я смотрю на процесс с pmap, ни одно из имен файлов журнала не показывается, поэтому я предполагаю, что они не отображены в памяти. И я прочитал (man pmap), что "[ anon ]" в столбце "Mapping" вывода pmap означает "выделенная память". Что это значит?:)

Тем не менее, pmap -x показывает:

Address           Kbytes     RSS   Dirty Mode   Mapping
...
----------------  ------  ------  ------
total kB        16928328  208824  197096

... так что я полагаю, что он не находится в ОЗУ, в конце концов... Но как он работает с памятью при открытии такого файла, поиске его до конца и т. д.?

Должен ли я беспокоиться обо всех этих ГБ памяти VIRT? Он "смотрит" 84 различных файла журнала прямо сейчас, и их общий размер на диске составляет 31414239 байт.

РЕДАКТИРОВАТЬ: Я только что проверил его на другом, менее "похожем на производство", Linux машине и не получил те же цифры. VIRT получил максимум до 2,5 ГБ. Я обнаружил, что некоторые настройки JVM по умолчанию были другими (проверено с помощью "java -XX: + PrintFlagsFinal -version"):

Value              Small machine    Big machine
InitialHeapSize    62690688         2114573120
MaxHeapSize        1004535808       32038191104
ParallelGCThreads  2                13

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

1 ответ

Решение

Пара вещей:

  • Каждый экземпляр Tailer будет иметь свой собственный поток. И у каждого потока есть стек. По умолчанию (в 64-битной JVM) стеки потоков по 1 МБ каждый, поэтому вы будете использовать 84 МБ для стеков. Вы можете уменьшить это, используя опцию -Xss во время запуска.

  • Большой размер вирта не обязательно плох. Но если это приводит к спросу на физическую память... и у вас не так много... тогда это действительно плохо.


Хм, я на самом деле запускаю его без каких-либо аргументов JVM. Хорошо это или плохо?:-)

Теперь я понимаю. Да, это плохо. Размер кучи JVM по умолчанию на большой 64-битной машине намного больше, чем вам действительно нужно.

Предполагая, что ваше приложение выполняет только простую обработку строк журнала, я рекомендую установить максимальный размер кучи на относительно небольшой размер (например, 64 МБ). Таким образом, если вы обнаружите утечку, это не повлияет на остальную часть вашей системы, поскольку поглощает много реальной памяти.

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