G1 GC - Большой фоновый ввод-вывод, приводящий к тому, что JVM не отвечает - пауза 8 секунд - PullRequest
0 голосов
/ 12 сентября 2018

У нас есть Java-приложение, которое требует ответа почти в реальном времени. Но мы также видим паузы до 8 секунд.

Особые условия работы:

  1. В некоторых интервалах приложение сериализует на диск (SSD) огромный моментальный снимок данных размером до 1,5 ГБ.
  2. Иногда какой-то тяжелый фоновый ввод-вывод происходит в результате какого-то другого сосуществующего процесса в т / х.

То, что мы наблюдаем, В ТЕЧЕНИЕ интервал, когда происходит эта большая запись сериализации, если случайно GC запускается, это вызывает огромную паузу в 6-8 секунд, JVM полностью не отвечает / замороженное состояние.

Из записи JFR видно, что

  1. ВСЕ потоки находятся в состояниях парковки / ожидания / сна, кроме той, которая записывает на диск.
  2. Для завершения GC G1 требуется около 200 мс.

Из журнала ГХ: 2018-09-05T18: 23: 40.277 + 0000: 39892.345: общее время, в течение которого потоки приложения были остановлены: 8.3785112 секунд, остановка потоков заняла: 8,3765855 секунд

Версия Java: Java-версия "1.8.0_181" Java (TM) SE Runtime Environment (сборка 1.8.0_181-b25) Java HotSpot (TM) 64-разрядная серверная виртуальная машина (сборка 25.181-b25, смешанный режим)

Вопросы:

  1. Почему такая 8-секундная не-GC JVM делает паузу, когда GC и фоновый ввод-вывод происходят одновременно?
  2. Как преодолеть эту большую паузу?

JFR файл: https://www.filehosting.org/file/details/756217/Run.jfr

1 Ответ

0 голосов
/ 13 сентября 2018

Ваша проблема не в GC, а в механике JVM Stop-The-World - safepoints . JVM ждет, пока все потоки не будут запаркованы в безопасной точке, прежде чем начинать работу, связанную с GC.

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

ОБНОВЛЕНИЕ: Поместить просто, если поток Java заблокирован при RandomFile / Channel методе чтения, это не мешает безопасной точке JVM. Но если поток Java заблокирован при операции чтения / записи в файле с отображенной памятью, JVM не может войти в безопасную точку, пока поток не будет разблокирован. Если такой доступ заключен в цикл, он может даже ожидать завершения цикла при определенных условиях.

Еще одна проблема, вызывающая длительное "Остановка потоков, занимаемых" - это циклы. Если у вас есть простой цикл с int counter, JVM считает его «быстрым» и может пропустить проверку безопасной точки в теле цикла.

...