У меня есть приложение для обработки данных scala, которое 95% времени может обрабатывать данные, брошенные в него в памяти. Остальные 5%, если их не остановить, обычно не попадают в OutOfMemoryError, а просто попадают в цикл основных GC, который всплескивает процессор, предотвращает выполнение фоновых потоков и, если он даже заканчивается, занимает 10x-50x, если он имеет достаточно памяти.
Я реализовал систему, которая может сбрасывать данные на диск и обрабатывать поток диска, как если бы он был итератором в памяти. Он обычно на порядок медленнее памяти, но достаточно для этих 5% случаев. В настоящее время я запускаю эвристику максимального размера контекста коллекции, который отслеживает размер различных коллекций, участвующих в обработке данных. Это работает, но на самом деле это всего лишь эмпирический порог adhoc.
Я бы скорее отреагировал на JVM, приблизившись к вышеупомянутому плохому состоянию и сбросившись на диск в то время. Я пробовал наблюдать за памятью, но не могу найти правильную комбинацию eden, old и т.д., Чтобы надежно предсказать смертельную спираль. Я также пытался просто наблюдать за частотой основных GC, но, похоже, также страдает от того, что у вас слишком широкий "слишком консервативный", чтобы "слишком поздно".
Будут оценены любые ресурсы для оценки состояния здоровья JVM и выявления проблемных состояний.