15

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

目前我知道(或认为我知道)的:

  • 所有对象(堆上)分配都四舍五入到 8 字节边界(或 2 的更大幂,由-XX:ObjectAlignmentInBytes.
  • G1
    • 对于小于区域大小(1 到 32 MB,可能在堆大小/2048 左右)的堆上分配,没有内部碎片,因为没有必要,因为分配器从不“填充漏洞”。
    • 对于区域大小较大的分配,它会将分配向上舍入到区域大小。IE。区域大小 + 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

4

1 回答 1

6
  • 据我了解,上述陈述是正确的,尽管 CMS 上的内容缺少很多上下文来解释它。
  • CMS 容易出现碎片化(在其运行 CMS 的旧空间中),这是其主要缺陷之一。如果它碎片太多,它可能偶尔不得不停止世界并进行全标记和(滑动)压缩以去除碎片,这会导致应用程序出现很大的停顿。正是这个缺陷经常被引用为开发 G1 的原因。一些系统(例如 HBase)故意使用固定大小的块进行大部分分配,以防止或显着减少碎片 CMS 以避免长时间停顿。
  • ParallelOldGC(或一般的“旧 GC”)不会分片。对象使用旧堆,当空间用完时,将运行一个完整的标记和紧凑的循环。它可以比任何其他分配器更快地执行此完整 GC,但是对于每 2 GB 堆的典型运行时间为 1 秒,这对于大型堆或延迟敏感的应用程序来说可能太长了。
  • Hotspot 根据目的使用了各种堆外分配策略。分配本机字节缓冲区不同于它自己对编译代码或分析数据的分配。我不能在这里就任何细节做出权威回答,但我只能假设其中大部分不使用系统分配器,否则 Hotspot 的性能不会像它那样好。此外,可以调整一些参数来控制其中的一些空间,例如-XX:ReservedCodeCacheSize,这表明这样的内存区域是通过间接而不是直接通过系统分配器来管理的。简而言之,如果系统分配器直接用于热点中的任何细粒度分配,我会感到相当惊讶。
于 2015-07-01T23:10:28.417 回答