2016-10-26 10 views
3

Мы используем систему RT в Java. Он часто использует относительно большие кучи (100 + ГБ) и обслуживает запросы, поступающие из очереди сообщений. Каждый запрос должен быть обработан быстро (< 100 мс) для удовлетворения SLA.Управление сборкой мусора Java в режиме реального времени

У нас возникли серьезные проблемы, связанные с GC, потому что часто бывает, что GC вызывает стоп-мировую коллекцию во время запроса (200 + мс), что приводит к сбою.

Один из наших разработчиков с разумным знанием GC провел некоторое время с настройкой параметров GC и попыткой использования разных GC. Через несколько дней он придумал некоторую параметризацию, которую мы в шутку называем «развитой генетическим алгоритмом». Это снижает паузы в GC, но по-прежнему далеки от удовлетворения требований SLA.

Решение, которое я ищу, чтобы защитить некоторые критические части коды от GC, и после того, как запрос будет завершен, пусть GC сделать столько работы, сколько ему нужно, до принятия следующего запроса. Случайные паузы за пределами запросов были бы в порядке, потому что у нас есть несколько рабочих и сборщиков мусора, которые просто не будут запрашивать запросы на некоторое время.

У меня есть некоторые идеи, которые глупо, некрасиво, и, скорее всего, не работает, но мы надеемся, что они иллюстрируют проблему:

  • Иногда называют Thread.sleep() в принимающем потоке, молясь за GC, чтобы сделать какую-то работу в Тем временем,
  • Invoke System.gc() или Runtime.gc() между запросами, снова безнадежно молясь за него, чтобы помочь,
  • Mess код полностью с Hacky узорами, как https://stackoverflow.com/a/6915221/1137187.

Последнее важное замечание, что мы стартап малобюджетный и коммерческие решения, такие как Zing® не вариант для нас, мы ищем некоммерческое решения.

Любые идеи? Мы полностью переписываем наш код на C++ (мы не знали, что GC может быть проблемой, а не решением в начале), но база кода слишком велика для этого.

+0

Java, конечно, не первый язык, который возникает у меня, когда я слышу термин «в реальном времени», и, учитывая, что Java выбрана, потребность в гигантской куче, похоже, не сулит ничего хорошего. –

+2

В любом случае в долговременном процессе есть только два общих подхода к проблеме GC: (1) уменьшить количество вывозимого мусора и (2) ускорить сбор мусора. Если полные GC являются дорогостоящими, но нечастыми, то одной из альтернатив может быть значительное уменьшение размера кучи. Для этого потребуются более частые GC, но каждый должен быть быстрее, потому что не может быть столько мусора для сбора. Кроме того, старайтесь избегать долгоживущих объектов, которые дороже для коллективного GC для сбора, если только они не сохраняются на протяжении всей жизни процесса. –

+2

Кроме того, позаботьтесь о временных объектах. Это не редкость для Java-кодеров, которые больше полагаются на GC, чем нужно, создавая и отбрасывая множество объектов. Они могут даже не признать, что они это делают. Например, конкатенация строк и автобоксинг могут здесь помочь. Примитивы не имеют стоимости GC, и, как правило, API более низкого уровня производят меньше мусора. –

ответ

1

Любые идеи?

Используйте другой JVM? Азул утверждает, что справляется с такими случаями. Redhat вносит свой вклад в openjdk с похожими целями, поэтому, возможно, вы можете попробовать экспериментальные сборки, если не хотите коммерческого решения.

Есть и другие JVM, ориентированные на приложения реального времени, но, как я понимаю, они фокусируются на более сложных требованиях реального времени к более мелким системам, а ваши звуки больше похожи на мягкие требования в реальном времени.

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

Выбор аппаратного обеспечения для максимальной пропускной способности памяти также может помочь.

Invoke System.gc() или Runtime.gc() между запросами, снова безнадежно молясь за него, чтобы помочь,

Это мощь работы в сочетании с -XX:+ExplicitGCInvokesConcurrent, в противном случае это вызовет однопоточная коллекция STW с CMS или G1 (я предполагаю, что вы используете один из них). Но этот подход кажется хрупким и требует много настроек и мониторинга.

+0

Я дал несколько попыток 'System.gc()' + '-XX: + ExplicitGCInvokesConcurrent', но он действительно не работает, главным образом потому, что' System.gc() 'работает в течение нескольких минут. Выполнение полного GC кажется не вариантом. И да, мы пытались использовать CMS и G1. Придется попробовать альтернативные JVM и профилировать + рефакторинг, если ничего не поможет. Однако, чем больше я об этом думаю, тем больше я убежден, что расскажу JVM о том, когда делать сборку именно в том, что нужно в моем случае. Параметры настройки GC не могут решить мою проблему в принципе, не давая дополнительной информации JVM. – Tregoreg

+0

Ну, вы говорите, что паузы в 200 мс, а ваше SLA составляет <100 мс. Таким образом, кажется, что в пределах досягаемости, если вы можете выжать 2-3 раза. – the8472

Смежные вопросы