Click on the blue font at the top and select “Set as star”

Garbage collection is essential, but it can be a performance killer if not handled properly. Take the following steps to ensure minimal and minimal GC pauses.

Long GC pauses are bad for the application, affecting the SLAS of the service, resulting in a poor user experience and serious damage to the services of the core application. Therefore, in this article, I’ve listed the key causes of long GC pauses and possible solutions to these problems.

1. Create objects at a high rate

If your application’s object creation rate is high, garbage recycling will be high to keep up. High garbage collection rates also increase GC pauses. Therefore, optimizing your application to create fewer objects is an effective strategy for reducing long GC pauses. This may be a time-consuming task, but it’s 100 percent worth it. To optimize the rate of object creation in your application, consider first using a Java profiler for analysis, such as JProfiler, YourKit, or JVisualVM, which reports the following information:

  • What objects are created?

  • What is the rate at which these objects are created?

  • How much space do they take up in memory?

  • Who is creating them?

Always try to optimize the object that occupies the largest amount of memory.

Tip: How do you calculate the object creation rate

Upload your GC logs to GCeasy, a general-purpose GC log analyzer tool. The tool reports the object creation rate. The Average creation rate is listed in Object Statistics. This item reports the object creation rate. Strive to keep the value low. See the figure below (an excerpt from the table of contents of the gCEASY-generated report) showing the “average creation speed” at 8.83 mb.sec.

2. Insufficient space for young generation

When the younger generation is too young, the object ascends prematurely into the older generation. It takes more time to collect garbage from older generations than from younger ones. Therefore, increasing the size of the young generation has the potential to reduce long GC pauses. You can increase the size of the younger generation by setting one of two JVM parameters:

-Xmn: specifies the size of the young generation.

-xx :NewRatio: Specifies the size ratio of the younger generation to the older generation. For example, setting -xx :NewRatio=2 indicates that the ratio between the younger generation and the older generation is 1:2. The young generation is going to be 1/3 of the size of the heap. Therefore, if the heap size is 2 GB, the young generation size will be 2G / 3 = 667 MB.

3. Select the GC algorithm

The GC algorithm has a great impact on the GC pause time. If you are a GC expert or plan to become one (or someone on your team is a GC expert), you can adjust the GC parameter configuration to get the best GC pause times. If you don’t have a lot of GC expertise, I recommend using the G1 GC algorithm because of its auto-tuning capabilities. In G1, the maximum expected GC pause time can be set using the system attribute -xx: MaxGCPauseMillis. Such as:


     

    -XX:MaxGCPauseMillis=200

Copy the code

Following the example above, the maximum GC pause time is set to 200 ms. This is a soft goal, and the JVM will try to achieve it.

4. The process uses Swap

Sometimes, due to insufficient physical memory (RAM), the operating system may swap data out of memory that is temporarily unused by the application. Swap action is very expensive because it requires disk access, which is much slower than physical memory access.

In my opinion, no significant application should be swapped in a production environment. When a process uses Swap, GC takes a long time to complete.

The script below is from StackOverflow (thanks to the author), and when the script executes, it shows all the processes in which the exchange is taking place. Make sure your application process does not use Swap.


     

    #! /bin/bash

    # Get current swap usage for all running processes

    # Erik Ljungstrom 27/05/2011

    # Modified by Mikko Rantalainen 2012-08-09

    # Pipe the output to "sort -nk3" to get sorted output

    # Modified by Marc Methot 2014-09-18

    # removed the need for sudo

    SUM=0

    OVERALL=0

    for DIR in `find /proc/ -maxdepth 1 -type d -regex "^/proc/[0-9]+"`

    do

    PID=`echo $DIR | cut -d / -f 3`

    PROGNAME=`ps -p $PID -o comm --no-headers`

    for SWAP in `grep VmSwap $DIR/status 2>/dev/null | awk '{ print $2 }'`

    do

    let SUM=$SUM+$SWAP

    done

    if (( $SUM > 0 )); then

    echo "PID=$PID swapped $SUM KB ($PROGNAME)"

    fi

    let OVERALL=$OVERALL+$SUM

    SUM=0

    done

    echo "Overall swap used: $OVERALL KB"</pre>

Copy the code

If you find that the process is using Swap, you can do one of the following:

  • Allocate more physical memory.

  • Reduce the number of processes running on the server so that it can free up memory (RAM).

  • Reduce the heap size of your application (I don’t recommend doing this because it can cause other side effects. It might solve your problem, though).

Adjust the number of GC threads

For each GC event reported in the GC log, the user, system, and actual execution time are printed. Such as:


     

    [Times: user= Times, real= Times]

Copy the code

If you consistently notice during GC events that real time is not significantly less than user time, it may indicate that there are not enough GC threads. Consider increasing the GC thread count. Assuming a user time of 25s and a GC thread count of 5, real should be closer to 5s (because 25s/5 = 5s).

Warning: Adding too many GC threads will consume a lot of CPU and thus your application’s resources. Therefore, sufficient testing is required before increasing the number of GC threads.

6. Background I/O activities

If there is a lot of file system I/O activity (that is, a lot of reads and writes), it can also lead to long GC pauses. This heavy file system I/O activity may not be caused by the application. This could be due to another process running on the same server. But it still causes the application to suffer long GC pauses.

When there is serious I/O activity, you will notice that the real time is significantly higher than the user time. Such as:


     

    [Times: user=0.20 sys=0.01, real=18.45 secs]

Copy the code

Here are some possible solutions when this happens:

  • If high I/O activity is caused by the application, optimize it.

  • Eliminate processes that cause high I/O activity on the server.

  • Move the application to another server with less I/O activity.

Tip: How do I/O activities be monitored

On Unix-like systems, you can monitor I/O activity using the SAR command (System Activity reporting). Such as:


     

    sar -d -p 1

Copy the code

The command above reports read/second and write/second statistics every second. You can refer to the resources for more details on the SAR command.

7. The System. The gc () call

When the System.gc() or Runtime.geTruntime ().gc() method is called, it causes a stop-the-world Full GC. During Full GC, the entire JVM is frozen (that is, no user activity is performed during this time). System.gc() calls generally come from the following situations:

  1. A developer might explicitly call the System.gc() method.

  2. Third-party libraries, frameworks, and sometimes even application servers used. Any of these may call the System.gc() method.

  3. It can also be triggered from external tools, such as VisualVM, using JMX.

  4. If your application is using RMI, RMI calls System.gc() periodically. This call interval can be configured using the following system properties:


     

    -Dsun.rmi.dgc.server.gcInterval=n

    -Dsun.rmi.dgc.client.gcInterval=n

Copy the code

It is absolutely necessary to evaluate whether to call system.gc () explicitly. If you don’t need it, delete it. On the other hand, you can force the System.gc() call -xx :+DisableExplicitGC to be disabled by passing JVM arguments.

Tip: How to know if system.gc () is called

Upload GC logs to GCeasy, a general-purpose GC log analyzer tool. This tool has a section called GCCauses. If a GC activity is triggered due to a system.gc () call, this section reports the situation. See the figure below (taken from the report directory generated by GCeasy), which shows that System.gc() was done four times in the life cycle of the application.

Caveat: All of the above strategies can only be extended to production after thorough testing and analysis. All strategies may not be applicable to your application. Can lead to negative results if not used properly.

The original address: https://dzone.com/articles/how-to-reduce-long-gc-pause

The recent hot,

  • JVM source code interpretation of CMS GC trigger conditions

  • Simple HTTP call, why so long delay?

  • Old GC occurs when the service starts.

If you like this article, please click on the picture below to follow our blog for more exciting content