Chapter 2. Java Virtual Machine Settings

2.1. Java Virtual Machine Settings

Tuning a Java Virtual Machine (JVM) is a complex task because of the number of configuration options and changes with each new release.

The recommended approach for performance tuning Java Virtual Machines is to use as simple a configuration as possible and retain only the tuning that is beneficial, rather than all tweaks. A collection of tested configurations for various heap sizes are provided after the parameters are discussed.

Heap Size

The JVM’s heap size determines how much memory is allowed for the application to consume, and is controlled by the following parameters:

  • -Xms - Defines the minimum heap size allowed.
  • -Xmx - Defines the maximum heap size allowed.
  • -XX:NewRatio - Define the ratio between young and old generations. Should not be used if -Xmn is enabled.
  • -Xmn - Defines the minimum and maximum value for the young generation.

In the majority of instances Xms and Xmx should be identical to prevent dynamic resizing of the heap, which will result in longer garbage collection periods.

Garbage Collection

The choice of which garbage collection algorithm to use will largely be determined by whether throughput is valued over minimizing the amount of the time the JVM is fully paused. As JBoss Data Grid applications are often clustered it is recommended to choose a low pause collector, such as Garbage First (G1) collector, to prevent network timeouts.

Important

The garbage collector, and options for each collector, will vary wildly based on the type of the workload. For this reason it is strongly recommended to test a variety of policies and tunings to determine the best configuration for each environment.

The following sections, beginning in Garbage Collectors discuss common tunables for three different garbage collection policies.

Large Pages

Large, or Huge, Pages are contiguous pages of memory that are much larger than what is typically defined at the OS level. By utilizing large pages the JVM will have access to memory that is much more efficiently referenced, and memory that may not be swapped out, resulting in a more consistent behavior from the JVM. Large pages are discussed in further detail at About Page Memory.

  • -XX:+UseLargePages - Instructs the JVM to allocate memory in Large Pages. These pages must be configured at the OS level for this parameter to function successfully.

Server Configuration

This parameter relates to JIT (Just-In-Time) compilation, which requires extended loading times during startup, but provides extensive compilation and optimization benefits after the startup process completes.

  • -server - Enables server mode for the JVM.

2.2. Garbage Collectors

2.2.1. Parallel Collector

The parallel collector maximizes throughput at the cost of all collections pausing the JVM. It behaves as the traditional, serial, collector, but uses multiple garbage collection threads running in parallel to collect unreferenced objects across both the old and young generations.

For additional information regarding the Parallel Collector refer to the JVM vendor’s documentation.

Commonly Configured Options

  • -XX:+UseParallelGC - This option enables the parallel collector on the JVM. For JVMs with -server specified this is the default collector.
  • -XX:+UseParallelOldGC - This option enables the parallel collector on the old generation, and should be used when the parallel collector is enabled.
  • -XX:MaxGCPauseMillis=<N> - This option is a suggestion regarding the maximum amount of time, in milliseconds, for the JVM to be paused due to a garbage collection. This value is not a guarantee that collections will result in the specified time or less; however, the collector will attempt to keep pauses shorter than the specified value by making adjustments to the throughput of the application.
  • -XX:ParallelGCThreads=<N> - By default the parallel collector uses a number of threads based on the number of cores in the system. For systems with 8 or fewer cores N is set to the value of cores, but for larger systems N is defined as 3 + ((ncpus * 5) / 8). This option is particularly important when multiple JVMs are running on the same system, as each JVM will calculate its own garbage collection thread pool independently of any other JVMs. In these instances it is recommended to define the number of garbage collection threads per JVM, with the total number of threads across all JVMs not exceeding the number of cores on the system.

2.2.2. Concurrent Mark Sweep (CMS) Collector

The Concurrent Mark Sweep (CMS) collector performs collections in a series of phases, and only two of these pause the JVM. This behavior makes the CMS collector useful for applications that want to minimize pause time, allowing the collector to run simultaneously with the application.

For additional information regarding the CMS Collector refer to the JVM vendor’s documentation.

Commonly Configured Options

  • -XX:+UseConcMarkSweepGC - Enables the CMS collector.
  • -XX:+UseParNewGC - Uses a parallel version of the young generation collector with the CMS collector, minimizing pause times by allowing multiple collection threads functioning in parallel.
  • -XX:+CMSClassUnloadingEnabled - Enables the CMS collector to sweep PermGen and remove unload classes that are no longer used.
  • -XX:+CMSScavengeBeforeRemark - Performs a young collection before the CMS remark phase, allowing the collector to minimize the pause time of the remark phase by having already pruned the young generation.
  • -XX:MaxGCPauseMillis=<N> - This option is a suggestion regarding the maximum amount of time, in milliseconds, for the JVM to be paused due to a garbage collection. This value is not a guarantee that collections will result in the specified time or less; however, the collector will attempt to keep pauses shorter than the specified value by making adjustments to the throughput of the application.
  • -XX:CMSInitiatingOccupancyFraction=<N> - This option controls when the CMS collector begins a concurrent collection of the tenured generation. By default, the tenured generation will begin to be collected when it is approximately 92% occupied; however, it may be useful to lower this threshold so that a collection begins earlier, reducing the chance of an OutOfMemoryError.
  • -XX:+UseCMSInitiatingOccupancyOnly - Enabling this option disables the CMS auto-tuning. If the load on the server fluctuates, such as drastically lower load overnight, it may be useful to disable this auto-tuning so that the JVM does not become adapted to lower load periods and delay collections during busier times.

2.2.3. Garbage First (G1) Collector

The Garbage First (G1) collector is another low-pause collector that divides the memory into a number of equally sized regions, each of which may be collected independently of another region. This allows the G1 collector to collect regions with the most unreachable objects, allowing more active regions to be used by the application without interference from the garbage collector.

For additional information regarding the G1 Collector refer to the JVM vendor’s documentation.

Commonly Configured Options

  • -XX:+UseG1GC - Enables the G1 collector.
  • -XX:+UseStringDeduplication - Enables the String deduplication feature, which will search for duplicate strings, update references so that only one active reference to the string exists, and then collect the duplicate. This feature reduces the memory footprint of the application.
  • -XX:InitiatingHeapOccupancyPercent=<N> - Sets the percentage of the entire heap at which the G1 collector will begin a marking cycle. Defaults to 45 percent of the total heap.
  • -XX:MaxGCPauseMillis=<N> - This option is a suggestion regarding the maximum amount of time, in milliseconds, for the JVM to be paused due to a garbage collection. This value is not a guarantee that collections will result in the specified time or less; however, the collector will attempt to keep pauses shorter than the specified value by making adjustments to the throughput of the application.
Note

Due to the way the G1 collector defines regions it is not recommended to explicitly define a young generation, as this will override the pause time goal.

2.3. Memory Requirements

Minimum Requirements

The default minimum amount of memory required to run JBoss Data Grid varies based on the configuration in use.

For Library mode the server should have a minimum of 1 GB of RAM for a single JBoss Data Grid instance, and is configured using the JVM arguments on the command line.

For Client-Server mode the requirements are determined based on the configuration file in use:

  • standalone.conf - The server should have a minimum of 2 GB of RAM for a single JBoss Data Grid instance, as the default heap may grow up to 1.3 GB, and Metaspace may occupy up to 256 MB of memory.
  • domain.conf - The server should have a minimum of 2.5 GB of RAM for a single JBoss Data Grid managed domain consisting of two JBoss Data Grid server instances, as the heap may grow up to 512 GB for the domain controller, the heap for each server instance may grow up to 256 MB, and the Metaspace may occupy up to 256 MB of memory for the domain controller and each server instance.

Recommended Memory Requirements

There is no official memory recommendation for JBoss Data Grid, as the memory requirements will vary depending on the application and workload in use; however, there are guidelines for memory usage as outlined below:

  • The amount of data in the heap should not exceed 50% of the total memory when only basic operations, such as put, get, remove, are used.
  • When using analytics, such as Queries, Streams, Distributed Executors, only 33% of the heap should be occupied. The extra memory allows the system to deal with memory allocations from these analytic operations with minimal impact.

It is strongly recommended to test each application, measuring throughput and collection times to determine if they are acceptable for the application in question.

Physical Memory Requirements

Each JVM process has a memory footprint that adheres to the following formula:

JvmProcessMemory = JvmHeap + Metaspace + (ThreadStackSize * Number of Threads) + Jvm-native-c++-heap

Adjusting these values are discussed in Java Virtual Machine Settings.

The Jvm-native-c++-heap will vary based on the native threads and if any native libraries are used; however, for a default installation it is safe to assume this will use no more than 256 MB of memory.

2.4. JVM Example Configurations

The following configurations have been tested internally, and are provided as a baseline for customization. These configurations show various heap sizes, which allows users to find one appropriate for their environment to begin testing:

8GB JVM using CMS

-server
-Xms8192m
-Xmx8192m
-XX:+UseLargePages
-XX:NewRatio=3
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+DisableExplicitGC

32GB JVM using G1

-server
-Xmx32G
-Xms32G
-XX:+UseLargePages
-XX:+UseG1GC
-XX:InitiatingHeapOccupancyPercent=70
-XX:MaxGCPauseMillis=3000
-XX:+DisableExplicitGC

64GB JVM using G1

-server
-Xmx64G
-Xms64G
-XX:+UseLargePages
-XX:+UseG1GC
-XX:InitiatingHeapOccupancyPercent=70
-XX:MaxGCPauseMillis=3000
-XX:+DisableExplicitGC