Понимание свойств внутренней фрагментации процесса Hotspot JVM
Как для кучи, так и для кучи. On-heap - в контексте трех основных сборщиков мусора: CMS, Parallel Old и G1.
Что я знаю (или думаю, что знаю) на данный момент:
- все выделения объектов (в куче) округляются до границы 8 байтов (или большей степени 2, настраиваются
-XX:ObjectAlignmentInBytes
, - G1
- Для выделений в куче, меньших, чем размер области (от 1 до 32 МБ, вероятно, около размера кучи / 2048), отсутствует внутренняя фрагментация, поскольку в этом нет необходимости, поскольку распределитель никогда не "заполняет дыры".
- Для распределений, превышающих размер региона, он округляет распределение до размера региона. И. е. выделение области размером + 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/
1 ответ
- Насколько я понимаю, приведенные выше утверждения верны, хотя в CMS немного не хватает контекста для его интерпретации.
- CMS подвержена фрагментации (в старом пространстве, где работает CMS), что является одним из ее основных недостатков. Если он слишком сильно фрагментируется, ему иногда может понадобиться остановить мир и сделать полную пометку, развернуть и сжать, чтобы удалить фрагментацию, что приводит к большой паузе в приложении. Именно на этот недостаток часто ссылаются как на то, почему был разработан G1. Некоторые системы (например, HBase) преднамеренно выполняют большую часть своих распределений с блоками фиксированного размера, чтобы предотвратить или значительно уменьшить фрагментирование CMS, чтобы избежать длительных пауз "остановка мира".
- ParallelOldGC (или "Старый GC" в целом) не фрагментируется. Объекты хранятся в старой куче, и когда в ней заканчивается свободное место, запускается полный цикл, развертка, компактный цикл. Он может выполнить этот полный сборщик мусора быстрее, чем любой другой распределитель, но с типичным временем выполнения в 1 секунду на 2 ГБ кучи это может быть слишком длинным для больших куч или приложений, чувствительных к задержке.
- Hotspot использовал различные стратегии для размещения вне кучи в зависимости от цели. Выделение собственных байтовых буферов отличается от его собственного выделения для скомпилированного кода или данных профилирования. Я не могу ответить авторитетно здесь по каким-либо деталям, но я могу только предположить, что большая часть этого не использует системный распределитель, иначе Hotspot не будет работать так же хорошо, как он. Кроме того, есть параметры, которые можно настроить, которые контролируют часть этого пространства, например
-XX:ReservedCodeCacheSize
, что предполагает, что такая область памяти управляется косвенным путем, а не напрямую через системный распределитель. Короче говоря, я был бы весьма удивлен, если системный распределитель использовался непосредственно для любого мелкозернистого распределения вообще в горячей точке.