Cranky users, critical processes failing, robots going haywire: all these are typical of application performance issues. Performance monitoring and tuning are vital for smooth-running systems.
In Java, garbage collection (GC) can often be the culprit if systems aren’t performing as they should. Even if GC is not to blame, GC logs can provide vital information about how systems are performing, and identify present and future bottlenecks.
Advanced Java GC Techniques
GC monitoring and tuning isn’t difficult, but you need to have a good understanding of how GC works and the JVM memory model.
You’ll need to know how to obtain GC logs, analyze them and use the information to tune your JVM settings.
You should also have a good understanding of the different GC algorithms available in Java. Each has its own strengths and weaknesses, and you need to choose the right algorithm for your application.
Briefly, the GC algorithms are:
- Serial: This was the original GC algorithm, and up until Java 4, it was the only one available. It used single-threading, and all other threads were paused during GC.
- Parallel: Introduced in Java 5, it used multithreading. Some tasks were performed concurrently with user threads.
- CMS (Concurrent Mark Sweep): This was experimental in Java 4, and performed many of the GC tasks concurrently with application threads. It was sometimes problematic, because it didn’t deal well with defragmentation. It was later deprecated and then discontinued.
- G1: This is the default algorithm in later versions of Java. Much of the work is done concurrently, and it’s efficient in most cases.
- Z: This is refined from G1 to deal better with larger heap sizes.
- Shenandoah: Also similar to G1, with improvements for working with large heaps.
- Epsilon: This is a do-nothing algorithm used purely for benchmarking other algorithms.
Obtaining GC Logs
You can request GC logs by using arguments on the command line when invoking your Java program. These arguments changed with Java 9.
For Java 8 and below, the arguments are:
-XX:+PrintGCDetails -Xloggc:<gc-log-file-path>-XX:+PrintGCDetails -Xloggc:<gc-log-file-path>-XX:+PrintGCDetails -Xloggc:<gc-log-file-path>
Enter fullscreen mode Exit fullscreen mode
For Java 9 and above, the argument is:
-Xlog:gc*:file=<gc-log-file-path>-Xlog:gc*:file=<gc-log-file-path>-Xlog:gc*:file=<gc-log-file-path>
Enter fullscreen mode Exit fullscreen mode
Analyzing GC Logs
GC logs are produced in text format, so it’s possible to read the file manually. However, they are usually very long, and it would be a time-consuming and difficult task.
JDK tools such as jstat
and jcmd
are useful in analyzing logs. However, one of the best tools is GCeasy. This produces useful stats, graphs and charts within minutes, and also gives performance tuning recommendations.
Key performance indicators that show whether garbage collection is working correctly include:
-
Throughput: The percentage of time spent on application tasks as opposed to GC tasks. For critical systems, you should aim at a throughput of at least 98%;
-
Latency: The time during which the application threads are paused waiting for GC events to complete. You should look at both maximum and average latency times.
-
Footprint: Resources used by GC.
GC Logging Best Practices
Here are a few tips for making good use of GC logs:
-
Monitor your logs regularly to pick up any problems that are developing before they become a major issue. This is where tools such as GCeasy are invaluable.
-
Always enable logs in production. If you have an issue, and logs aren’t enabled, it may be difficult to replicate the problem in order to solve it.
-
Always monitor over a 24-hour period, so you can assess what’s happening during low and high traffic times.
-
Use the right GC algorithm.
-
Avoid using excessive GC logging arguments on the command line: for most purposes, the arguments shown in the previous section are sufficient.
-
Avoid using log rotation. This can often result in losing the very log that you most need. Instead, suffix the GC log file name with %t, which adds a timestamp to the log name.
-
Use a suitable tool such as GCeasy to analyze the logs, and pay attention to the results.
Tuning the GC Algorithm
Java includes a wide range of command line arguments that you can use to tune your applications. Once you’ve made informed decisions based on the GC logs, you can tweak your JVM settings in various ways, including:
-
Adjusting the heap size;
-
Adjusting the size/ratio of spaces within the heap;
-
Controlling how quickly objects are promoted to the next heap space;
-
The percentage of used space at which GC is activated;
-
The number of concurrent and parallel GC threads;
-
Enabling or disabling string deduplication;
-
Changing the GC algorithm.
There may be occasions where resources such as CPU cores and memory are insufficient, and must be upgraded. If this is the case, regular monitoring of the GC logs helps you to plan ahead and put solutions in place before performance is dangerously downgraded.
You may also need to refactor your code to ensure memory is released in a timely manner.
Each of the GC algorithms requires a different tuning strategy. This article, What is Java Garbage Collection? contains links to specific tuning guides for each algorithm, as well as in-depth information on how garbage collection works.
Conclusion
A good understanding of Java garbage collection is essential for maintaining good performance, especially in critical systems.
Simple tweaks to the garbage collector can result in huge performance gains at very little cost. If your application is running in the cloud, you could be paying for CPU and memory resources you wouldn’t actually need if your GC worked correctly. Uber reduced their costs dramatically with a few changes to GC operations.
If you need to up your performance tuning skills, you may like to look at this Performance Tuning and Troubleshooting Masterclass.
原文链接:Advanced Garbage Collection Techniques and Best Practices
暂无评论内容