The paper come zhongjue shallow must know this to practice

The company I work for basically doesn’t have the opportunity to do JVM parameter tuning, but if you haven’t experienced something yourself, no amount of theoretical knowledge is really just a piece of paper and you still don’t know how to analyze it when it comes to real problems. So they make some problems and then look at the phenomenon, using the knowledge learned beforehand to speculate, to see whether the phenomenon is the same as their speculation. This will not only reinforce what you have learned, but also exercise your problem-solving skills (even if they are of your own making).

Actually have seen good before writing this article several times about the JVM tuning that piece of content, whether book or blog, but mostly finished feel understood, but the real simulation of the operation time and think what all can’t, but after their simulation again found before able to relate all the knowledge, form a face, I feel like I understand a little bit better. I want to emphasize that once you’ve seen this, you’ll be able to run your own simulations on the machine, using different parameters and then make your own guesses and verify them

Tools to prepare

To do a good job, he must sharpen his tools. Before analyzing the JVM, we need to prepare tools, one is a visual garbage collection tool, the other is a pressure measurement tool.

GcViews installation

  1. willGcViewsThe code is downloaded from GitMaking the address
  2. Execute commands in the root directory of your projectmvn clean install
  3. It then found that it was generated in the root directorytargetFolder. You can find it in thereGcviewer - 1.37 - the SNAPSHOT. The jarfile

JMeter install

Apache JMeter is an open source stress testing tool, JMeter is based on Java development, JMeter is not only used for Web stress testing, but also for open source based on access software to do stress testing, static files, databases, FTP, SSH, etc

  • Download JMeter, download address
  • Unzip it. My address is/ Users/hupengfei/apache jmeter - 5.1.1
  • Open the terminal to access itbinUnder the directory
  • Execute the commandsh jmeter

I won’t go into details about how to configure the parameters in the JMeter Http stress test. You can read this article.

The theory is introduced

For JVM tuning, this is about JVM garbage collection optimizations, which are usually needed because there are problems. So for JVM GC, if you observe that your application server processes are running high CPU usage, and you see frequent GC times and long GC pauses in the GC log, This indicates that you need to optimize GC.

In the process of GC tuning, it is not necessary for us to know some GC principles, but more important to skillfully use a variety of tools that can be monitored and analyzed, and have the actual GC tuning ability. Currently, the two most used garbage collectors are CMS and G1. Starting with Java9, G1 was adopted as the default garbage collector, and G1 was also intended to gradually replace CMS. So let me briefly describe the differences between the two collectors.

You can use the Java -xx :+PrintCommandLineFlags -version command to view some of the default parameters in the output from the command line. You can view the default garbage collectors for each version here

  • Java 7: Parallel GC
  • Java 8: Parallel GC
  • Java 9: G1 GC
  • Java 10: G1 GC

CMS collector

The CMS collector divides the Java heap into young and old generations (the permanent generation was removed in Java8 and converted into a meta-space, which is stored directly in memory and not in the JVM). This is mainly because studies have shown that more than 90 percent of objects are recycled on the first GC, but a few survive for longer periods of time.

CMS also divides the young generation into two parts, one is Survivor space and the other is Eden space. New objects are always created in Eden space, and once an object survives a garbage collection, it is moved to the survivor space. When an object survives multiple garbage collections, it is moved to the tenor generation. The purpose of this is to use different garbage collection algorithms in the young generation and the old generation to achieve higher collection efficiency. For example, due to the short life time of objects in the young generation, there are fewer objects left in a garbage collection, so copy-collation algorithm is adopted. However, in the old age, objects live for a long time, and there may be fewer objects recovered and more objects left in a garbage collection, so the mark-collation algorithm is adopted.

G1 collector

Compared to CMS, G1 has two main features

  • G1 can do most of The GC work concurrently without “stop-the-world”
  • The G1 uses discontinuous space, which allows it to handle very large heaps efficiently, and it can collect both young and old generations. Rather than splitting the Java heap into three Spaces (Eden, Survior, and Old), G1 divides the heap into many very small regions. The size of these areas is fixed (by default, each area is 2MB). Each area is allocated a space.

The U in the figure represents the unallocated area. G1 divides the heap into small areas. One of the biggest benefits is the ability to do local area garbage collection, rather than collecting the whole area at a time, such as young and old generations, so that the pause time of collection is shorter. The collection process is roughly as follows

  • Copy all surviving objects from the collected region to the unallocated region. For example, if the collection region is Eden space, copy the survivable objects in Eden to the unallocated region, and the unallocated region becomes a Survior space. Ideally, if a region is all garbage (meaning that there are no survivable objects), then the region can be declared “unallocated” directly.
  • To optimize collection time, G1 always prioritizes areas with the most garbage to minimize the amount of work required to allocate and free heap space later. This is where the G1 collector gets its name, garbage-first

We practice

I use version Java8 and the Java garbage collector is CMS

I will use the GC log analysis tool to observe the GC activity and locate the problem.

First we set up a SpringBoot program as our tuning object. The code is as follows:

 1@RestController

2@Slf4j

3public class GcTestController {

4

5    private List<Greeting> objListCache = new ArrayList<>();

6

7    @RequestMapping("/greeting")

8    public Greeting greeting() {

9        Greeting greeting = new Greeting();

10        if (objListCache.size() >= 100000) {

11            log.info("clean the List!!!!!!!!!!");

12            objListCache.clear();

13        } else {

14            objListCache.add(greeting);

15        }

16        return greeting;

17    }

18}

19

20@Data

21class Greeting {

22    private String message1;

23    private String message2;

24    private String message3;

25    private String message4;

26    private String message5;

27    private String message6;

28    private String message7;

29    private String message8;

30    private String message9;

31    private String message10;

32    private String message11;

33    private String message12;

34    private String message13;

35    private String message14;

36    private String message15;

37    private String message16;

38    private String message17;

39    private String message18;

40    private String message19;

41    private String message20;

42}

Copy the code

The above code creates a pool of objects that will be emptied once the pool reaches 100,000 to simulate older objects. Here you can take advantage of my last article millions of data into memory and not overwhelm the system? Figure out how much memory 10W objects take up in memory. I’m just going to say that 100,000 Greeting objects take up about 10 meters of space.

Therefore, I set the startup parameters in Idea as follows

1-Xmx52m -Xmn9m -Xss256k -XX:+PrintGC -XX:+UseConcMarkSweepGC -Xloggc:/Users/hupengfei/Downloads/gclog/gc.log

Copy the code

I set the initial heap size of the program to be 52MB and the size of the young generation to be 9MB. The default Eden/Survior ratio in the young generation is 4:1, so the Eden/Survior ratio in the young generation is about 7.2MB. The purpose is to show that objects not recovered in Eden will enter the old age. Young GC will occur if the Eden region is full.

We then use the JMeter pressure tool to send test requests to the program. Note that I set the access time here to 10 minutes, and then a thread to access continuously.

After ten minutes we can open the GC log using the GCViewer tool and we see the following figure

  • The blue line: represents the size of the heap in use, and we see that its period oscillates up and down because our object pool is emptied until it reaches 100,000.
  • Bottom green line: indicates GC activity, and we can see that frequent GC is triggered as heap usage increases
  • The black line in the middle: represents Full GC, and we can see that the blue line drops with Full GC, indicating that Full GC reclaims older objects

Based on what is shown in the picture above, we can draw a conclusion that the set of young generation is not enough. Why is such a conclusion reached?

  • High GC activity: you can see that the green lines are more dense
  • The memory of the Java heap can be reclaimed after Full GC, indicating that it is not a memory leak

As shown on the left side of GCView, we can see that the total GC occurred 1622 times, with one Full GC occurring.

Then, with the total heap size unchanged, we just resize the young generation to 16MB, and then we look at the figure below

We can see that while there is still a Full GC, the younger generation GC is not as frequent. And the cumulative GC pause time is only 1.48 seconds

What if we still want to optimize? I’m just going to keep increasing the total size of the heap, so let’s set the heap to 200MB, the young generation to 80MB, and let’s see what happens.

As you can see, there is no Full GC in the same period of time, and there are fewer GC occurrences in the younger generation

Tuning strategy

For the CMS collector, where we want to set a reasonable young and old generation size, you might ask is there a fixed formula? I don’t actually have one here, the tuning process is an iterative process where you can take the JVM defaults and then pressure analyze the GC logs. Observe GC collection under different conditions.

If we see frequent Minor GC, and frequent GC is not efficient, our objects are not being collected as quickly, we can scale up the young generation appropriately and watch.

If we see high memory usage in the older generation, Full GC occurs frequently. This is generally divided into two cases

  • If the memory usage of the old generation does not come down each time the Full GC occurs, there may be a memory leak and you need to check the code
  • If the memory usage is lower after Full GC, it is not a memory leak, and you can consider aging

The code address

The test code has been posted on GitHub github.com/modouxiansh… And put the GC log of my many tests in it. If you don’t want to try it yourself, you can download the GC log and see the picture below

The author’s writing skill is still shallow, if there is something wrong, please point out generously, will be grateful

conclusion

The knowledge on paper, or in books or on the Internet, is ultimately the author’s own experience summary. There must be an author’s train of thought. But not necessarily with the actual combination, more importantly, a sentence to convey accurate information is not everyone read that kind of text description can get. If you have exactly that kind of experience, it resonates.

I believe that people read to learn, and learning is precisely for their own growth. So the center of learning is people, not books. The essence of learning is to combine what you have learned with yourself. If you do not combine with yourself, you can not resonate with the knowledge of the book, it is difficult to deeply understand the truth in the book, and naturally it is difficult to remember this truth.

Most of the knowledge in the book is the author’s own understanding and comprehension, so it is difficult to reproduce the scene that resonates with the author in the mind of the reader, so that the author can also resonate with the reader. Therefore, “it comes from the end sleep is shallow on the paper”. Only by deconstructing the knowledge in books and connecting it with ourselves, “we have to practice to know everything”, we can understand ourselves and the world we live in while learning knowledge, gain resonance in our hearts and consolidate knowledge.

So I will also emphasize again and again in my article, if you want to have a more profound knowledge of this aspect, then you must run on the machine yourself, observe yourself, modify a few parameters, verify the situation. Maybe you can’t touch the pit I hit, and I can’t touch the pit you hit. Then you encounter this pit to solve their own ability to improve.

reference

  • Check out GCVIEWER, one of GC’s best tools
  • JMeter Http stress test JMeter Http stress test JMeter Http stress test
  • In-depth understanding of the Java virtual machine
  • JVM GC principle and the basic idea of tuning
  • Delve into the JVM road Metaspace |
  • Garbage Collection in Java (3) – Concurrent Mark Sweep
  • Let’s talk about GC optimization for Java applications from a practical example