Почему Sun JVM продолжает потреблять все больше RSS-памяти, даже когда размеры кучи и т. Д. Стабильны?

За прошедший год я сделал огромные улучшения в использовании Java-кучи моего приложения - солидное сокращение на 66%. Для этого я отслеживал различные метрики, такие как размер кучи Java, процессор, не-куча Java и т. Д. Через SNMP.

Недавно я отслеживал объем реальной памяти (RSS, резидентный набор) JVM и был несколько удивлен. Реальная память, используемая JVM, кажется полностью независимой от размера кучи моих приложений, не-кучи, пространства eden, количества потоков и т. Д.

Размер кучи, измеренный Java SNMP График использования кучи Java http://lanai.dietpizza.ch/images/jvm-heap-used.png

Реальная память в КБ. (Например: 1 МБ КБ = 1 ГБ) График использования кучи Java http://lanai.dietpizza.ch/images/jvm-rss.png

(Три провала на графике кучи соответствуют обновлениям / перезапускам приложения.)

Это проблема для меня, потому что вся эта дополнительная память, которую потребляет JVM, - это «кража» памяти, которая может использоваться ОС для кэширования файлов. Фактически, как только значение RSS достигает ~ 2,5-3 ГБ, я начинаю видеть более медленное время отклика и более высокую загрузку ЦП в моем приложении, в основном в ожидании ввода-вывода. Как только начинается переход к разделу подкачки, это очень нежелательно.

Итак, мои вопросы:

Почему это происходит? Что происходит"под капотом"?Что я могу сделать, чтобы контролировать реальное потребление памяти JVM?

Кровавые детали:

RHEL4 64-bit (Linux - 2.6.9-78.0.5.ELsmp # 1 SMP Ср 24 сентября 2008 г. x86_64 ... GNU / Linux)Java 6 (сборка 1.6.0_07-b06)Tomcat 6Приложение (потоковое видео по запросу HTTP)Высокий ввод / вывод через java.nio FileChannelsОт сотен до сотен тысяч темНизкое использование базы данныхВесна, спящий

Соответствующие параметры JVM:

-Xms128m  
-Xmx640m  
-XX:+UseConcMarkSweepGC  
-XX:+AlwaysActAsServerClassMachine  
-XX:+CMSIncrementalMode    

-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps  
-XX:+PrintGCApplicationStoppedTime  
-XX:+CMSLoopWarn  
-XX:+HeapDumpOnOutOfMemoryError 

Как я измеряю RSS:

ps x -o command,rss | grep java | grep latest | cut -b 17-

Это входит в текстовый файл и регулярно считывается в базу данных RRD моей системы мониторинга. Обратите внимание, что ps выводит килобайты.

Проблема и решениеs:

Хотя в итоге это былоATorrasответ, который оказался в конечном итоге правильным, этоkdgregory который направил меня к правильному пути диагностики с использованиемpmap, (Идите, проголосуйте за оба их ответа!) Вот что происходит:

Вещи, которые я знаю наверняка:

Мое приложение записывает и отображает данные сJRobin 1.4что-то, что я кодировал в своем приложении более трех лет назад.Самый загруженный экземпляр приложения в настоящее время создаетБолее 1000 новых файлов базы данных JRobin (около 1,3 МБ каждый) в течение часа после запуска~ 100+ каждый день после запускаПриложение обновляет эти объекты базы данных JRobin каждые 15 секунд, если есть что написать.В конфигурации по умолчанию JRobin:используетjava.nioна основе доступа к файлам. Это фоновые картыMappedByteBuffers к самим файлам.раз в пять минут вызывается нить демона JRobinMappedByteBuffer.force() на каждой базе данных JRobin MBBpmap в списке:6500 отображений5500 из которых составляли 1,3 МБ файлов базы данных JRobin, что составляет ~ 7,1 ГБ

Этот последний пункт был моим«Эврика!» момент.

Мои корректирующие действия:

Рассмотрите возможность обновления до последней версии JRobinLite 1.5.2, которая, по-видимому, лучшеРеализуйте правильную обработку ресурсов в базах данных JRobin. На данный момент, как только мое приложение создает базу данных, а затем никогда не выгружает ее после того, как база данных больше не используется активно.Эксперимент с перемещениемMappedByteBuffer.force() для обновления базы данных, а не периодический таймер. Проблема волшебным образом исчезнет?Немедленноизмените внутреннюю часть JRobin на реализацию java.io - изменение строки. Это будет медленнее, но, возможно, это не проблема. Вот график, показывающий непосредственное влияние этого изменения.

В памяти Java RSS используется график http://lanai.dietpizza.ch/images/stackoverflow-rss-problem-fixed.png

Вопросы, которые я могу или не могу успеть выяснить:

Что происходит внутри JVM сMappedByteBuffer.force()? Если ничего не изменилось, он все еще записывает весь файл? Часть файла? Это загружает это сначала?Всегда ли определенное количество MBB всегда в RSS? (RSS составляла примерно половину от общего размера выделенных MBB. Совпадение? Я подозреваю, что нет.)Если я переедуMappedByteBuffer.force() к событиям обновления базы данных, а не периодическому таймеру, проблема волшебным образом исчезнет?Почему уклон RSS был таким регулярным? Это не соответствует ни одной из метрик загрузки приложения.

Ответы на вопрос(4)

Ваш ответ на вопрос