了解Hotspot JVM进程的内部碎片属性

lev*_*tov 15 java memory-management jvm-hotspot heap-fragmentation memory-fragmentation

对于堆上和堆外分配.在堆上 - 在三个主要垃圾收集器的上下文中:CMS,Parallel Old和G1.

我所知道的(或者我认为我知道)到目前为止:

  • 所有对象(堆上)分配都向上舍入到8个字节的边界(或更大的2的幂,由...配置)-XX:ObjectAlignmentInBytes.
  • G1
    • 对于小于区域大小的堆上分配(1到32 MB,可能在堆大小/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

Sco*_*rey 5

  • 据我了解,上面的陈述是正确的,尽管CMS上的位缺少很多上下文来解释它。
  • CMS易于碎片化(在CMS运行所在的旧空间),这是其主要缺陷之一。如果碎片太多,则有时可能不得不停止工作并进行完整的标记,扫掠和压缩以除去碎片,这会导致应用程序中的大量暂停。正是这种缺陷经常被认为是开发G1的原因。某些系统(例如HBase)有目的地使用固定大小的块进行大多数分配,以防止或显着减少CMS碎片,从而避免长时间的停顿。
  • ParallelOldGC(或通常为“ Old GC”)不会分段。对象被保留到旧堆中,当旧空间用完时,将运行完整标记,清除和紧凑循环。它可以比其他任何分配器更快地完成完整的GC,但是每2 GB堆的典型运行时间为1秒,对于大堆或对延迟敏感的应用程序来说,这可能太长了。
  • 热点根据目的使用了各种策略进行堆外分配。分配的本机字节缓冲区不同于其自身对已编译代码或分析数据的分配。在这里,我无法就任何细节获得权威的答复,但我只能假设其中的大部分未使用系统分配器,否则Hotspot的性能将不及它。此外,可以调整一些参数来控制某些空间,例如-XX:ReservedCodeCacheSize,这表明这种内存区域是通过间接而非直接通过系统分配器进行管理的。简而言之,如果在热点完全将系统分配器直接用于任何细粒度的分配,我会感到非常惊讶。