Paul7979
Paul7979

Reputation: 281

Criteria for default garbage collector Hotspot JVM 11/17

I found a source describing that the default gc used changes depending on the available resources. It seems that the jvm uses either g1gc or serial gc dependnig on hardware and os.

The serial collector is selected by default on certain hardware and operating system configurations

Can someone point out a more detailed source on what the specific criteria is and how that would apply in a dockerized/kubernetes enivronment. In other words:

Could setting resource requests of the pod in k8s to eg. 1500 mCpu make the jvm use serial gc and changing to 2 Cpu change the default gc to g1gc? Do the limits on when which gc is used change depending on jvm version (11 vs 17)?

Upvotes: 23

Views: 23161

Answers (2)

apangin
apangin

Reputation: 98324

In current OpenJDK, G1 GC is chosen by default for the "server class machine", or Serial GC otherwise. "Server class machine" is defined as a system with 2 or more non-HT CPUs and 2 or more GiB RAM.

The exact algorithm can be found in src/hotspot/share/runtime/os.cpp:

// This is the working definition of a server class machine:
// >= 2 physical CPU's and >=2GB of memory, with some fuzz
// because the graphics memory (?) sometimes masks physical memory.
// If you want to change the definition of a server class machine
// on some OS or platform, e.g., >=4GB on Windows platforms,
// then you'll have to parameterize this method based on that state,
// as was done for logical processors here, or replicate and
// specialize this method for each platform.  (Or fix os to have
// some inheritance structure and use subclassing.  Sigh.)
// If you want some platform to always or never behave as a server
// class machine, change the setting of AlwaysActAsServerClassMachine
// and NeverActAsServerClassMachine in globals*.hpp.
bool os::is_server_class_machine() {
  // First check for the early returns
  if (NeverActAsServerClassMachine) {
    return false;
  }
  if (AlwaysActAsServerClassMachine) {
    return true;
  }
  // Then actually look at the machine
  bool         result            = false;
  const unsigned int    server_processors = 2;
  const julong server_memory     = 2UL * G;
  // We seem not to get our full complement of memory.
  //     We allow some part (1/8?) of the memory to be "missing",
  //     based on the sizes of DIMMs, and maybe graphics cards.
  const julong missing_memory   = 256UL * M;

  /* Is this a server class machine? */
  if ((os::active_processor_count() >= (int)server_processors) &&
      (os::physical_memory() >= (server_memory - missing_memory))) {
    const unsigned int logical_processors =
      VM_Version::logical_processors_per_package();
    if (logical_processors > 1) {
      const unsigned int physical_packages =
        os::active_processor_count() / logical_processors;
      if (physical_packages >= server_processors) {
        result = true;
      }
    } else {
      result = true;
    }
  }
  return result;
}

Upvotes: 24

usuario
usuario

Reputation: 2467

In JDK 11 and 17 Serial collector is used when there is only one CPU available. Otherwise G1 is selected

If you limit the number of CPUS available to your container, JVM selects Serial instead of the defaultG1

JDK11

1 CPU

docker run --cpus=1 --rm -it eclipse-temurin:11 java -Xlog:gc* -version
[0.004s][info][gc] Using **Serial**

It uses Serial

More than one CPU

docker run --cpus=2 --rm -it eclipse-temurin:11 java -Xlog:gc* -version
[0.008s][info][gc     ] Using G1

It uses G1

JDK17

1 CPU

docker run --cpus=1 --rm -it eclipse-temurin:17 java -Xlog:gc* -version
[0.004s][info][gc] Using Serial

It uses Serial

More than one CPU

docker run --cpus=2 --rm -it eclipse-temurin:17 java -Xlog:gc* -version
[0.007s][info][gc] Using G1

It uses G1

Upvotes: 37

Related Questions