#java #garbage-collection #protocol-buffers
#java #сборка мусора #протокол-буферы
Вопрос:
У меня есть сервер jetty, который проксирует между серверной частью и конвертирует protobufs frontend.proto-> backend.proto и backend.proto-> frontend.proto.
Время выполнения запросов составляет менее 20 мс (99-й) и 40 мс (99,9-й), пока загрузка не достигла максимума.
Однако, когда нагрузка достигает максимума, 99-й увеличивается на 10, а 99,9-й увеличивается на 60.
Я исследовал это, и отложенные запросы вызваны паузами эвакуации GC, в этом я уверен, эти паузы занимают 50-70 мс и выполняются раз в 15 секунд при загрузке долины, но увеличиваются до одного раза в 3-5 секунд при пиковой нагрузке, продолжительность такая же.
Как только частота GC становится ниже 8-9 секунд, 99,9-й процентиль взлетает вверх, и я могу видеть журналы отладки медленных запросов одновременно с журналом GC.
Я профилировал с помощью JProfiler, Yourkit и VisualVM и увидел, что:
- Пространство Eden заполняется, и запускается пауза GC
- Очень немногие объекты перемещаются в Survivor (несколько МБ из 12G)
- Таким образом, срок действия большинства объектов в Eden уже истек
- Это имеет смысл, поскольку запросы занимают 30-40 мс, и большая часть времени жизни объектов привязана к времени жизни запроса
- Большинство объектов создаются во время десериализации protobuf
Я пробовал играть с размерами GCPauseMillis и Eden, но, похоже, ничего не меняет, это никогда не занимает меньше 50 мс, а больший Eden означает меньшую частоту, но гораздо более длительные паузы
Я вижу здесь 2 варианта:
- Каким-то образом повторно использовать создание объектов в java-protobuf: кажется невозможным, прочитал множество сообщений и рассылок, и это не так настроено, они просто говорят, что «Распределение объектов Java очень эффективно, и оно должно быть способно обрабатывать многие создаваемые объекты», и хотя это правда, связанные с этим затраты на сборку убивают мои 99,9 тыс.
- Заставьте GC запускаться чаще, скажем, раз в секунду, чтобы сократить время сбора, чтобы оно останавливало больше запросов, но на более короткое время: я играл с размерами GCMaxMillis и Eden, но, похоже, я не могу уменьшить их
Я загрузил журнал gc в gc_log
Версия Java:
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
Подробности GC:
-XX:CICompilerCount=12 -XX:ConcGCThreads=5 -XX:ErrorFile=/home/y/var/crash/hs_err_pid%p.log -XX: FlightRecorder -XX:G1HeapRegionSize=4194304 -XX:GCLogFileSize=4194304 -XX: HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/y/logs/yjava_jetty -XX:InitialHeapSize=12884901888 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=12884901888 -XX:MaxNewSize=7730102272 -XX:MinHeapDeltaBytes=4194304 -XX:NumberOfGCLogFiles=10 -XX: ParallelRefProcEnabled -XX: PrintGC -XX: PrintGCDateStamps -XX: PrintGCDetails -XX: PrintGCTimeStamps -XX: UnlockCommercialFeatures -XX: UseCompressedClassPointers -XX: UseCompressedOops -XX: UseFastUnorderedTimeStamps -XX: UseG1GC -XX: UseGCLogFileRotation
Комментарии:
1. Можете ли вы добавить к вопросу подробности о том, какую Jvm и сборщик мусора вы используете.
2. @SilverShroud готово!
3. Проверка выходных данных журнала, копирование объекта, похоже, вызывает всплеск. Но размер оставшегося в живых или старого поколения, похоже, не увеличивается в этих случаях (возможно, ошибка). Я бы попробовал обновленные версии java 8 runtime, чтобы посмотреть, ведет ли она себя так же. Вы также можете попробовать поиграть со следующими значениями, чтобы ограничить размер eden space -XX:G1NewSizePercent -XX:G1MaxNewSizePercent
4. @SilverShroud Я провел еще несколько тестов, и прикосновение к ручкам G1, похоже, не работает, хотя переключение на CMS помогло, задержка сильно снизилась, потому что эвакуация Eden, похоже, не приостанавливается с CMS. Использование CMS действительно кажется немного отсталым, в то время как G1 намного современнее.
5. Я думаю, что эти флаги являются экспериментальными флагами. Чтобы иметь возможность их использовать, должен быть установлен какой-то другой флаг. (посмотрите на это, если вы это пропустили)