10

JVM c1, c2 compiler thread – High CPU consumption?

 2 years ago
source link: https://devm.io/java/jvm-c2-c2-cpu
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

JVM c1, c2 compiler thread – High CPU consumption?

C1 and C2 compiler threads are created by Java virtual machine to optimize your application’s performance. Occasionally these threads will tend to consume high CPU. In this post, let’s learn a little more about C1 and C2 compiler threads and how to address their high CPU consumption.

After reading this post, terminologies like Hotspot JIT, C1 compiler threads, C2 compiler threads, and code cache may not terrify you (as they used to terrify me in the past).

What is a Hotspot JIT compiler?

Your application may have millions of lines of code. However, only a small subset of code gets executed again and again. This small subset of code (also known as a ‘Hotspot’) is responsible for your application performance. At runtime, JVM uses this JIT (just in time) compiler to optimize this hotspot code. Most of the time, code written by the application developers is not optimal. Thus, JVM’s JIT compiler optimizes the developer’s code for better performance. To do this optimization, the JIT compiler uses C1 and C2 compiler threads.

What is Code Cache?

The memory area that the JIT compiler uses for this code compilation is called the ‘Code Cache’. This area resides outside of the JVM heap and metaspace. To learn about different JVM memory regions, you may refer to this video clip.

What is the difference between C1 & C2 compiler threads?

During the early days of Java, there were two types of JIT compilers:

  • a. Client
  • b. Server

Based on what type of JIT compiler you want to use, appropriate JDKs have to be downloaded & installed. Say you are building a desktop application, then the JDK which has a ‘client’ JIT compiler needs to be downloaded. If you are building a server application, then the JDK which has a ‘server’ JIT compiler needs to be downloaded.

Client JIT compiler starts compiling the code as soon as the application starts. The server JIT compiler will observe the code execution for quite some time. Based on the execution knowledge it gains, it will start doing the JIT compilation. Even though server JIT compilation is slow, code it produces will be far more superior and performant than the one produced by Client JIT compiler.

Today modern JDKs are shipped with both Client & Server JIT compilers. Both the compilers try to optimize the application code. During the application startup time, code is compiled using client JIT compiler. Later, as more knowledge is gained, code is compiled using server JIT compiler. This is called tiered compilation in JVM.

JDK developers were calling them Client and Server JIT compilers, internally known as C1 and C2 compilers. Thus, the threads used by client JIT compiler are called C1 compiler threads. Threads used by the server JIT compiler are called C2 compiler threads.

C1, C2 compiler threads default size

The default number of C1 and C2 compiler threads are determined based on the number of CPUs that are available on the container/device in which your application is running. Here is the table which summarizes the default number of C1 and C2 compiler threads:

CPUs C1 threads C2 threads
1 1 1
2 1 1
4 1 2
8 1 2
16 2 6
32 3 7
64 4 8
128 4 10

Table 1: Default C1 and C2 compiler thread count

You can change the compiler thread count by passing ‘-XX:CICompilerCount=N’ JVM argument to your application. One-third of the count you specify in ‘-XX:CICompilerCount’ will be allocated to the C1 compiler threads. The remaining thread count will be allocated to C2 compiler threads. Say, suppose you are going to 6 threads (i.e., ‘-XX:CICompilerCount=6’), then 2 threads will be allocated to C1 compiler threads and 4 threads will be allocated to C2 compiler threads.

C1 and C2 compiler thread high CPU consumption – Potential solutions

Sometimes you might see C1 and C2 compiler threads consume a high amount of CPU. When this type of problem surfaces, below are the potential solution to address it:

1. Do Nothing (if intermittent)

In your case, if your C2 compiler thread’s CPU consumption is only intermittently high and not continuously high, and it doesn’t hurt your application’s performance, then you can consider ignoring the problem.

2. -XX:-TieredCompilation

Pass this ‘-XX:-TieredCompilation’ JVM argument to your application. This argument will disable the JIT hotspot compilation. Thus, CPU consumption will go down. However, as a side-effect, your application’s performance can degrade.

3. -XX:TieredStopAtLevel=N

If the CPU spike is caused because of C2 compiler threads alone, you can turn off C2 compilation alone. You can pass ‘-XX:TieredStopAtLevel=3’. When you pass this ‘-XX:TieredStopAtLevel’ argument with value 3, then only C1 compilation will be enabled and C2 compilation will be disabled.

There are four tiers of compilations:

Compilation Level Description
0 Interpreted Code
1 Simple C1 compiled code
2 Limited C1 compiled code
3 Full C1 compiled code
4 C2 compiled code

When you say ‘-XX:TieredStopAtLevel=3’, then code will be compiled only up to the ‘Full C1 compiled code’ level. C2 compilation will be stopped.

4. -XX:+PrintCompilation

You can pass the ‘-XX:+PrintCompilation’ JVM argument to your application. It will print details about your application’s compilation process. It will facilitate you to tune the compilation process further.

5. -XX:ReservedCodeCacheSize=N

Code that the Hotspot JIT compiler compiles/optimizes are stored in the code cache area of the JVM memory. The default size of this code cache area is 240MB. You can increase it by passing ‘-XX:ReservedCodeCacheSize=N’ to your application. Say if you want to make it 512 MB, you can specify it like this: ‘-XX:ReservedCodeCacheSize=512m’. Increasing the code cache size has the potential to reduce the CPU consumption of the compiler threads.

6. -XX:CICompilerCount

You can consider increasing the C2 compiler threads by using the argument ‘-XX:CICompilerCount’. You can capture the thread dump and upload it to tools like fastThread, where you can see the number of C2 compiler threads. If you see a fewer number of C2 compiler threads and you have more CPU processors/cores, you can increase the C2 compiler thread count by specifying ‘-XX:CICompilerCount=8’ argument.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK