理解Hotspot JVM进程的内部碎片特性

15

针对堆内和堆外分配,涉及到三种主要的垃圾收集器CMS、Parallel Old和G1。

当前我所了解(或者认为自己了解)的情况如下:

  • 所有对象(堆内分配)的分配都会向上舍入至8字节边界(或更大的2的幂次方,由-XX:ObjectAlignmentInBytes配置)。
  • G1
    • 对于小于区域大小(1到32MB,可能在堆大小 / 2048附近)的堆内分配,不存在内部碎片,因为没有必要,分配器从不“填补空隙”。
    • 对于大于区域大小的堆内分配,将其舍入至区域大小。例如,分配区域大小+1字节非常不幸,将浪费近50%的内存。
  • CMS唯一找到的相关信息是

    Naturally old space PLABs mimic structure of indexed free list space. Each thread preallocates certain number of chunk of each size below 257 heap words (large chunk allocated from global space).

    引自http://blog.ragozin.info/2011/11/java-gc-hotspots-cms-promotion-buffers.html。 据我理解,这里的“全局空间”是主要的老年代。

问题:

  • 上述陈述是否正确?
  • 在CMS中,主要老年代的碎片化属性如何?超过“257个堆字”的分配情况如何?
  • Parallel Old GC如何管理老年代?
  • Hotspot JVM是否使用系统内存分配器进行堆外分配,还是使用特定的分配器进行重新管理?

更新:讨论线程:https://groups.google.com/forum/#!topic/mechanical-sympathy/A-RImwuiFZE


(Note: The original text was already in Chinese, so I have simply translated it into English without modifying the html tags.)

2
你为什么想要这样做?请记住,这些东西会因实现方式和更新而有所不同。如果你想要进行优化,我认为最好的方法是查阅最新的文章。毕竟2011年已经过去了一段时间。 - markspace
关于您的第四点,查看源代码,很容易发现,在当前热点中,它们使用普通的malloc来进行分配。入口点是sun.misc.Unsafe.allocateMemory。 - Alexandre de Champeaux
我很困惑:这个问题并没有简单的答案,但请注意像@markspace所说的那样,当处理低级主题(如分段、世代排列等)时,你应该小心谨慎。这些的实现可能会在一个版本到另一个版本(主要版本)之间或在一个更新到另一个更新之间有很大的差异,因此使得你的实现有点像瞎猜一样。 如果另一方面,你的问题是为了知识而问,我也想听听专家对你提出的一些观点的意见! - witchedwiz
@AlexandredeChampeaux Unsafe.allocateMemory 并不是大部分内存分配的地方。大部分内存分配发生在此之前(在启动期间),堆的增长是通过单个大内存分配实现的。普通对象分配不会经过该路径,任何其他托管内存区域(例如 JIT 编译的字节码所在的区域)也不会经过该路径。 - Scott Carey
@ScottCarey 这取决于您的用例。但是我假设他想要的信息是关于本地字节缓冲区的,这确实有点限制性。 - Alexandre de Champeaux
显示剩余3条评论
1个回答

6
据我了解,上面的陈述都是正确的,尽管关于CMS的部分缺少很多上下文来解释它。
CMS容易发生碎片化(在其旧空间中运行的CMS),这是其主要缺陷之一。如果它碎片化得太厉害,有时可能不得不停止应用并进行完整的标记和(滑动)整理以消除碎片化,这会导致应用程序中的大暂停。正是这个缺陷经常被引用为G1开发的原因。一些系统(例如HBase)故意使用固定大小的块进行大多数分配,以防止或显著减少碎片化CMS以避免长时间的停顿。
ParallelOldGC(或总体上的“老GC”)不会发生碎片。对象被晋升到老年代堆,并在其耗尽空间时运行完整的标记和压缩周期。它可以比其他分配器更快地运行此全GC,但对于大型堆或延迟敏感的应用程序,典型的运行时间为每2 GB堆1秒,这可能太长。
Hotspot根据目的使用各种策略进行堆外分配。分配本机字节缓冲区与分配编译代码或分析数据有所不同。我无法在这里准确回答任何细节问题,但我只能假设其中很多都不使用系统分配器,否则Hotspot不会像它表现得那样好。此外,有一些参数可以调整以控制部分空间,例如"-XX:ReservedCodeCacheSize",这表明此类内存区域是通过间接方式进行管理而不是直接通过系统分配器进行管理。简而言之,如果Hotspot中有任何细粒度的分配直接使用系统分配器进行操作,我会感到非常惊讶。

你大多数关注于外部碎片。我的问题是关于内部碎片的。 - leventov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接