2016-05-01 12 views
0

Я использую кеш Infinispan для хранения значений. Код записывает в кеш каждые 10 минут, а кеш достигает размера около 400 МБ. У этого есть время, чтобы жить приблизительно 2 часа, и максимальные записи составляют 16 миллионов, хотя в настоящее время в моих тестах количество записей не превышает 2 миллиона или около того (я вижу это, проверяя mbeans/metrics в jconsole).Размер кучи Java слишком велик с кешем Infinispan

Когда я начинаю jboss, размер кучи java составляет 1.5Gb до 2Gb. Значение -Xmx для максимальной выделенной памяти для jboss равно 4Gb.

Когда я отключу кеш Infinispan, использование памяти кучи остается ровным от 1,5 ГБ до 2 ГБ. Он очень постоянный и остается на этом уровне.

=> Проблема в том, что когда у меня есть кеп Infinispan включен, размер кучи java увеличивается примерно до 3,5 Гбит/4 ГБ, что намного больше, чем ожидалось. Я сделал кучу дампа, чтобы проверить размер кеша в Eclipse MAT, и это всего лишь 300 или 400 Мб (это нормально). Так что я ожидал бы, что использование памяти будет идти до 2.5 Гб и останется устойчивым на этом уровне, так как начальный размер кучи составляет 2 ГБ, а максимальный размер кеша должен быть всего около 500 МБ.

Однако он продолжает расти и расти со временем. Каждые 2 или 3 часа выполняется сбор мусора, и это приводит к сокращению использования до 1 или 1,5 ГБ, но затем снова увеличивается в течение 30 минут до 3,5 ГБ. Число записей остается стабильным примерно в 2 миллионах, так что это связано не только с увеличением количества записей в кеш. (Также число выселений остается равным 0).

Что может быть связано с этим объемом памяти, если кеш составляет всего 400-500 МБ? Это проблема с настройками моей мусорной корзины? Или я должен посмотреть настройки Infinispan?

Спасибо!

Редактировать: вы можете видеть размер кучи с течением времени здесь. Странно, что даже после того, что выглядит как полный GC, память снова возвращается к 3Gb. Это соответствует большему количеству записей в кеш. Java heap over time

Редактировать: Оказывается, это не имеет ничего общего с Infinispan. Я сузил проблему до одной строки кода, которая использует много памяти (около 1 ГБ больше, чем без вызова). Но я думаю, что все больше и больше памяти берется в кепсе Infinispan, естественно, потому что добавляется больше записей за 2 часа времени для жизни.

У меня также должно быть 50 запросов пользователей на Infinispan. Когда куча достигает такого высокого значения (даже без упомянутой выше утечки памяти), я знаю, что это не сценарий ошибок в java, но мне нужно как можно больше памяти. Есть ли способ «ободрить» кучу дампа за определенный момент? Я попытался использовать опции GC для сбора в определенной пропорции кучи для старого поколения, но в целом использование кучи имеет тенденцию к ползучести.

+0

это позволяет столько, сколько ему разрешено, здесь нет технической проблемы, а ваши ожидания не согласуются с принятием решений JVM. http://stackoverflow.com/a/28614001/1362755 – the8472

+0

Какова конфигурация кеша, которую вы используете? –

+0

timeToLive составляет 2 часа, максимальное количество записей - 16 миллионов (в запуске на скриншоте загружено около 2 миллионов записей), стратегия выселения LRU, транзакция ложна, режим кэширования реплицируется async, тип видимости кеша - это кластер. Количество распределенных владельцев - 10. – user2533268

ответ

4

Возможно, вы видите, что JVM не собирает объекты, которые были выселены из кеша. Кэши вообще имеют любопытные отношения с преобладающей идеей генерации GC.

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

Кэш нарушает этот шаблон, имея промежутки времени жизни промежуточной длины (т. Е. Несколько секунд/минут/часов, в зависимости от вашего кеша). Эти объекты часто получают продвижение в поколение, где их обычно не рассматривают до тех пор, пока не будет необходим полный GC, даже после того, как они будут выведены из кеша.

Если это то, что тогда происходит у вас несколько вариантов:

  • игнорировать его, пусть полный GC Семантика делать свое дело и просто быть в курсе, что это то, что происходит.
  • попытайтесь настроить GC так, чтобы объекты занимали больше времени, чтобы получить продвижение к поколению. Есть некоторые GC flags, которые могут помочь в этом.
+0

Спасибо, я выставил изображение с объемом памяти кучи, используемой с течением времени. Интересно, что даже после полного GC память возвращается снова через 3Gb очень быстро. – user2533268

+0

Вы можете увидеть фазы программы на диаграмме GC: 7 минут тяжелой обработки с помощью мусора из мусора, возможно, это когда вы обновляете кеш? Тогда это 8 минут устойчивый и спокойный поток, возможно, вы просто получаете доступ к кешу? Полный GC происходит в фазе тяжелой обработки, потому что у вас высокий уровень распределения. Конечно, он вернется к 3 ГБ очень быстро. – cruftex

+0

Поскольку полный GC происходит на третьей из вас фазы обновления, две трети данных, которые вы заменяете дальше, будут застревать до следующего полного GC. Для экспериментов вы можете добавить System.gc() сразу после фазы обновления и посмотреть, что из-за всей его разницы. – cruftex