Понимание внутренних свойств фрагментации процесса Hotspot JVM

Для распределений на кучу и вне кучи. On-heap - в контексте трех основных сборщиков мусора: CMS, Parallel Old и и G1.

То, что я знаю (или думаю, что знаю) на данный момент:

  • распределения всех объектов (по-куче) округляются до 8-байтовой границы (или большей мощности 2, с настройкой -XX:ObjectAlignmentInBytes.
  • G1
    • Для распределений на куче, меньших размера региона (от 1 до 32 МБ, вероятно, вокруг размера кучи /2048), нет внутренней фрагментации, потому что нет необходимости, потому что распределитель никогда не "заполняет отверстия".
    • Для распределений большего размера региона он округляет распределение до размера региона. I. e. выделение области размером + 1 байт очень неудачно, оно отнимает почти 50% памяти.
  • Для CMS единственная релевантная информация, которую я нашел, -

    Естественно старые PLAB-схемы пространства имитируют структуру индексированного свободного списка. В каждом потоке выделяется определенное количество блоков каждого размера ниже 257 слов кучи (большой фрагмент, выделенный из глобального пространства).

    От http://blog.ragozin.info/2011/11/java-gc-hotspots-cms-promotion-buffers.html. Насколько я понимаю, "глобальное пространство" - это основное старое пространство.

Вопросы:

  • Правильны ли приведенные выше утверждения?
  • Каковы свойства фрагментации основного старого пространства в CMS? Что относительно распределений более чем "257 слов кучи"?
  • Как управлять старым пространством с помощью Parallel Old GC?
  • Использует ли Hotspot JVM распределитель системной памяти для распределений вне кучи или перенаправляет его с помощью специального распределителя?

UPD. Тема обсуждения: https://groups.google.com/forum/#!topic/mechanical-sympathy/A-RImwuiFZE

Ответы

Ответ 1

  • Насколько я понимаю, приведенные выше утверждения правильны, хотя бит в CMS не содержит большого контекста для его интерпретации.
  • CMS подвержена фрагментации (в ее старом пространстве, где работает CMS), что является одним из его основных недостатков. Если он фрагментирует слишком много, иногда может потребоваться остановить мир и выполнить полную метку, развертку и сжатие, чтобы удалить фрагментацию, что приводит к большой паузе в приложении. Именно этот недостаток часто упоминается как причина G1. Некоторые системы (например, HBase) специально выполняют большую часть своих распределений с блоками фиксированного размера, чтобы предотвратить или значительно сократить фрагментацию CMS, чтобы избежать длительных пауз в мире.
  • ParallelOldGC (или "Старый GC" вообще) не фрагментирует. Объекты переносятся на старую кучу, и когда она заканчивается из космоса, запускается полный метка, развертка, компактный цикл. Он может делать этот полный GC быстрее, чем любой другой распределитель, но с типичным временем работы 1 секунду на 2 ГБ кучи, это может быть слишком большим для больших кучи или приложений с чувствительностью к задержкам.
  • Hotspot использовал различные стратегии для распределения вне кучи в зависимости от цели. Выделение собственных байт-буферов отличается от собственного распределения для скомпилированного кода или профилирующих данных. Я не могу отвечать с полномочиями здесь ни на какие подробности, но могу только предположить, что большая часть этого не использует системный распределитель, иначе Hotspot не будет работать так же хорошо, как и он. Кроме того, есть параметры, которые можно настроить таким образом, чтобы управлять некоторым из этого пространства, например. -XX:ReservedCodeCacheSize, который предполагает, что такая область памяти управляется посредством косвенной передачи, а не напрямую через системный распределитель. Короче говоря, я был бы весьма удивлен, если бы системный распределитель был напрямую использован для любого мелкозернистого выделения вообще в точке доступа.