Last year in the investigation of a lot of java applications, see some of the phenomenon is the programmer to run on their own environment to read the program rarely lead to troubleshooting problems will be more frustrating, so think of writing this series of articles, procedures To provide functionality to end-users, the code is only one part of it, and it needs to be relied on for jvm, os, server hardware, networking, load balancing, etc. In this series of articles, Several parts, more is only a popular science role, because os I use are linux, os talked about in this series are also the default linux, this is the first of this series: CPU.
What is the relationship between a Java program and a CPU at run time, how to use it and how to use the CPU more fully, and what are some of the ways we can control the CPU. This is the focus of this article. If so Have you want to pay attention, but not mentioned here, as well as some mistakes in this article, are welcome to reply, :)
First of all need to know the CPU status of the machine running the program, at least know how many CPU, CPU model, is not open Hyper Thread (Hyper Thread), etc., this information will have a significant impact on the performance of the program ( The performance and throughput improvements that a better model brings are noticeable, so do not be surprised to see a variety of performance reports that do not provide a description of the hardware environment for Ultra NB.) These can be done by running on a machine On cat / proc / cpuinfo to get, if it is a virtual machine, then see the information may be a bit strange, for example, some virtual machines will see the virtual cpu, this can only go to the host to view.
In / proc / cpuinfo where you can see the specific number of cpu, cpu model, HT is open according to the physical id and core id to determine, if you see the two id of the two processors are consistent, then the instructions are turned on HT, open HT for supporting the scene of high concurrency is basically good and bad, generally can improve about 60% (but can not double the increase, it is not possible to do so).
In cpuinfo will see there are flags in this column, interested can learn more, some will have a significant impact on the operation of the application performance, of course, these can also be some more understanding of the cpu model.
In understanding the machine's CPU hardware, you can take a look at the process of Java program execution and the relationship between the CPU, Java program is a process, multi-threaded way to perform, Java threads and OS threads can be one to one relationship, Many-to-one relationship, many more This is because the previous multi-threaded support for Linux is not good, so you can think of Java threads and OS threads are usually one-to-one relationship.
Since it is a one-to-one relationship, so thread-specific access to the CPU's execution time slice by the OS to control (the virtual machine will be more complicated point, you have to talk about some of the virtualization point of knowledge, and then write it later ), The process started by default can use all the machines on the CPU, but also through the taskset command to control a process can use the CPU, and even more fine to control a thread to use the CPU (because in linux Thread to some extent can also be considered as "process").
Linux is a time-sharing scheduling operating system, the thread in Runnable state will be scheduled according to the time slice (how to go to the specific scheduling os, how to protect multiple core cpu is more balanced, it is recommended to refer to the appropriate operating system Article or book), the Java program will enter different thread states according to the executed code during execution. Specifically, the state of the thread may be checked through the jstack that comes with Java. However, the thread state seen by jstack may not be correct, for example, Very often will see epollWait such code corresponding to the thread has been in Runnable, in fact, more because jstack by default can only see the status of the Java stack, but many times when the Java code depends on native code, so This is usually the time to see the state of the thread may be wrong, in the relatively new version of java, jstack-m can be directly through the native stack and Java stack together, in which case it will be accurate a lot of.
So you can think of Java programs more by changing the state of the thread to a certain extent interfere with the use of cpu, such as disruptor these more real-time scheduling is called, by a very short wait time or direct (true) Most of the time to ensure that the thread is runnable, the same is also a lot of code such as sleep is also used to take the initiative to release the cpu method.
If you want to run the thread to obtain more execution opportunities, it seems Java provides thread priority setting is more useful, but because of the priority of os and have a great relationship, and not necessarily reasonable , So not better, for the application is running the key to the thread, for example, in a communication-intensive java program, nio io processing thread may be critical, but usually nio io processing threads will be few, and other threads If you are in the case of time-sharing scheduling, then there may be some circumstances io processing thread to get the execution opportunity is not enough, for this special case can be used taskset to solve, and some students may think it will think of that jvm is how some of its threads to enjoy high executive powers, such as gc threads, which will speak later when talking about memory.
In the process of running through the top-H to see the running CPU application of each thread consume CPU status, if you see the phenomenon is the constant consumption of CPU threads, and each thread does not consume the CPU More, it shows that the application's health is good (of course, this situation may also have optimization space), whereas if you always see a high percentage of cpu consumption by individual threads, you need to check what is the reason By seeing the thread id do hexadecimal conversion, and then correspond to the jstack out of the thread information nid, take a look at the stack to do specific actions, a better way is through perf this tool to view, but the default version Perf is unable to count through the c2 compiled cpu optimized CPU code consumption, will be counted to ?, so the search will help a lot will appear a lot less, this should be amended to support perf and jvm Caixing.
For Java programs, more needs to be considered is how to fully play cpu, and for most Java applications, usually other hardware resources will not become a bottleneck, so write Java programs with the amount of concurrent increase The case, it should be possible to run full cpu.
top press the number 1 you can see the consumption of each cpu core, there will be several indicators, respectively, corresponding to the user mode consume the consumption of the system kernel transferred value of the process of cpu us cpu idle iowait consumption hard interrupt response consumption Consumption of soft interrupt response is consumed by other virtual machines to run full cpu, not one of the cpu core id This value is close to 0, but should be all cpu Core id are close to 0 is reasonable, and for the Java program, it should be as high as possible to run this value us.
Some applications may appear even if the concurrency increases, but the cpu id has been down or down us or not, in troubleshooting the bottleneck is not the problem of other hardware resources, the following may be the following reasons:
1. The processing of the number of threads is not enough, most of the request processing is not all consumed cpu, such as lock waiting, io wait and so on, this time the thread will enter the blocked or waiting state, such as running the thread is not enough, It will lead to cpu us not go now java applications come in from the request until the real deal, usually through multiple thread pool, so check this kind of problem must be clear when the entire process, and then look at each The process of the number of threads is not enough to determine whether it is still relatively easy to use, jstack If you see all the threads are executing the appropriate application code, rather than waiting for the thread pool wait, it basically shows the number of threads May not be enough, in which case you can try to increase the thread pool thread try to see if the cpu utilization can go up, but this place is not very good toss is the number of threads in the end set to what is appropriate, too small cpu can not be fully used, too much may cause all the more surviving after the operation of the thread more, resulting in increased Java heap memory also increased, resulting in frequent g c, the problem is more serious, so the thread pool thread has been set up how much is a painful problem, basically rely on experience and test in different hardware settings to set the dynamic seemingly have not found any good way, if We all know, please recommend, :)
2 Another situation is that the thread pool has increased the number of threads, but still no effect, this is usually possible during the processing of concurrent threads in the processing part of the serial time-consuming, for example, need the same Locks and other scenarios, this can usually be seen through jstack, the need to do is introduce a variety of high concurrency skills, especially lock-free data structure or lock granularity control to solve.
Under normal circumstances, if we can solve the above two problems, it is basically the case with the rise in the amount of concurrent cases, the cpu also take full advantage of, if you encounter a strange one of the cpu consumption has been A lot higher than the other and become a bottleneck phenomenon, it may be caused by the processing of network adapter interrupt, this can look at my previous article on the network card interrupt.