【问题标题】:Why is SerialGC chosen over G1GC?为什么选择 SerialGC 而不是 G1GC?
【发布时间】:2018-09-24 07:03:09
【问题描述】:

我在非常相似的 VM 上运行 java,但我找不到为什么在一种情况下选择 SerialGC 而不是 G1GC 的解释。它在 AWS 上是相同的 Java 版本、相同的操作系统、相同的 VM 实例类型,我怀疑唯一的区别是容器设置,但我不知道如何查明发生了什么变化。有没有办法解释为什么 VM 决定选择此设置或其他设置?

两种情况下的Java版本:

java version "10.0.1" 2018-04-17 Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10) Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

在一种情况下运行java时:

java -XX:+PrintFlagsFinal -XX:+PrintCommandLineFlag

输出:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 -XX:InitialHeapSize=253366976 -XX:MaxHeapSize=4053871616 -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC [Global flags] (...) bool UseG1GC = false {product} {default} bool UseParallelGC = false {product} {default} bool UseSerialGC = true {product} {ergonomic}

还有一个:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 -XX:G1ConcRefinementThreads=8 -XX:InitialHeapSize=253480064 -XX:MaxHeapSize=4055681024 -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC [Global flags] (...) bool UseG1GC = true {product} {ergonomic} bool UseParallelGC = false {product} {default} bool UseSerialGC = false {product} {default}

【问题讨论】:

  • 你说“非常相似的虚拟机”。这意味着存在差异。您是否检查过 -version 确实给出了完全相同的结果。
  • 嗯,是的,这就是我想要确定的。 java 是完全相同的(将其添加到原始问题中) - 作为整个 docker 图像。但它是不同的 AWS AMI,我们以不同的方式部署映像(直接使用 k8s 而不是 docker)。
  • 您使用串行收集器的虚拟机是否可能只有一个 CPU?
  • 我在这两种情况下都运行了cat /proc/cpuinfo,并且在这两种情况下都可以看到 8 个 vCPU。
  • 我知道你正在使用 docker/k8s。所以我认为重要的是分配给 docker 容器的 cpu 数量,而不是虚拟机。您能否也检查一下 - 分配给 docker 容器的 cpu 数量、cpu 配额和/或 cpu 份额。

标签: java garbage-collection jvm


【解决方案1】:

-XX:+PrintFlagsFinal 中的{ergonomic} 表示该标志是根据可用处理器的数量和 RAM 的数量自动设置的。

JDK 10 treats machine as "server" 如果它至少有 2 个可用 CPU 和 2 GB RAM。这可以被覆盖 -XX:+AlwaysActAsServerClassMachine-XX:+NeverActAsServerClassMachine JVM 标志。

“服务器”配置默认使用G1 as the default GC,而“客户端”机器默认使用SerialGC

为了计算可用处理器的数量,JDK 不仅使用操作系统中可见的 CPU,还使用处理器关联和 cgroup 限制,包括

  • cpu.shares
  • cpu.cfs_quota_us
  • cpuset.cpus

由于您在容器中运行 Java,因此容器可能会施加 cgroup 限制,从而导致可用 CPU 数量或内存量减少。使用-Xlog:os+container=trace 查找每个特定环境中的有效限制。

【讨论】:

  • 非常感谢。原来这是主机上使用的 ubuntu 的回归,现在一切正常。但有趣的是获得一些关于如何决定的见解!
猜你喜欢
  • 1970-01-01
  • 2012-10-24
  • 1970-01-01
  • 2020-01-15
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多