📜 ⬆️ ⬇️

More about Java performance

“There is a big lie, there is a small one, but there are Java performance statistics.”

Recently, I began to notice an abundance of Java performance tests with a surprisingly incredible range of test results. The results differ to the exact opposite, depending on who conducts the tests.

Many understand that such tests are part of marketing. And those who order it, order the result. But the awesomeness of the situation is that there is no one to blame for lies. It is impossible to deny the truth of those tests in which Java is inferior to C #, nor to those tests in which Java is superior to C ++ (not C). The problem is that such tests are focused mainly on novice developers in order to lure more programmers into their camp and thereby increase the commercial appeal of the platform for business. And in such tests deliberately missed are difficult to understand the details of the work of dynamic JIT compilation and adaptive optimization HotSpot, in which novice programmers rarely go.
')
What is it fraught with? Banal cognitive dissonance.

Once I also wrote a comparative test program for Delphi and Java. And I got almost a ten-fold lag in Java performance. Of course, you could write everything down on your crooked hands, so I tried to figure out the JIT compilation mechanism. After all, if it’s not in the hands, and Java really creates such inefficient native code, then you need to keep as far away from such a platform as possible. But reality says that this is one of the most common industrial programming languages, and a business with such a loss of productivity will not be tolerated.

I will try to explain on the fingers as I understand the essence of what is happening in the depths of Java, and if I am mistaken about something, then please correct me. Since, despite the persistence, the essence of some processes remained a mystery to me.

To begin with, the adaptive JIT compilation is a content overhead procedure, and compiling all the code at once is too expensive. Yes, it is not necessary. According to the statistics of industrial applications, programs spend 80% of the time in 20% of the code. It is these 20% most profitable to compile. The rest of the code will not have a significant effect on performance even if it is executed in the interpretation mode. In order to calculate these 20% you need to thoroughly study the algorithm. And to study all the algorithms HotSpot requires the collection of significant statistics, so at the beginning the whole program works in the interpretation mode.

As statistics accumulate, the compiler compiles the application in parts. The minimum unit of compilation is considered a function. In the client configuration, before the JIT compiler starts working, 1500 function calls are assigned to collect statistics. For a server configuration where more aggressive optimization is performed, 15,000 calls are required. This should be enough to collect statistics and conduct speculative code optimization, which allows you to give a high bandwidth code. On high-load systems, statistics are collected instantly, which is not the case with desktop programs.

In the process of optimization, the compiler puts forward hypotheses about the functioning of the code and analyzing the statistics tries to prove or disprove its assumptions. If HotSpot refutes its hypothesis, then the JIT compiler produces a de-optimization for subsequent recompilation of the already compiled code. And conducts new optimizations for new hypotheses. Most often, HotSpot puts forward hypotheses about the structure of the algorithm according to standard design patterns. That is why all Java programmers are taught to use design patterns as often as possible.

Even if you can come up with an original efficient algorithm, this does not mean that your program will run faster, rather the opposite. HotSpot will too often put forward false hypotheses about your code, carry out de-optimizations and recompilations until it can find the best way to compile your algorithm. And it's not a fact that JIT optimization of a non-standard algorithm will be better than optimization of a bulky pattern. SUN engineers at one time did an enormous amount of work to teach Java how to work effectively with patterns.

Among the common optimizations, HotSpot can convert a slow call to a virtual function to inline substitutions. But for this, HotSpot should know about all polymorphic transformations in your program. Knowing where a particular function is most often called, the compiler moves it as close as possible to the place where it is used. A similar level of performance can be achieved in C when manually controlling inline calls. But using the object-oriented paradigm in C ++ is difficult and sometimes impossible. Therefore, with a sufficiently large collection of statistics, HotSpot can approach C performance and exceed C ++. And if we use patterns, HotSpot recognizes them and makes the necessary substitutions from the first time. But if you have a nonstandard algorithm, then in this case the HotSpot hypothesis about the performed substitutions will turn out to be false with greater probability. And although new statistics will be collected for more efficient optimization, the JIT compiler runs at strictly defined intervals of iterations.

By default, as mentioned above, this is 1500 iterations for desktop programs. This may seem like a big deal. In this case, the behavior of HotSpot can be changed using the -XX: CompileThreshold parameter. By this we can reduce the time for warming up HotSpot. But by reducing the time for warming up, we will not reduce the time for collecting statistics. Statistics are collected based on the activity of the program. Therefore, setting the value too low -XX: CompileThreshold = 1, we only force the JIT compiler to work idle very often, especially after the start, when the new statistics is received continuously. This will also distort performance statistics. With modern processor power, the optimal value can be considered -XX: CompileThreshold = 100. But for interest, I recommend experimenting with this parameter, as it is very sensitive to the algorithm. To monitor the operation of the JIT compiler, use the -XX option in the console: + PrintCompilation. I assure you, this will be a very informative observation.

Thus, the performance test result depends on how long HotSpot has been collecting statistics on the algorithm. And if there are no statistics, then there is no JIT compilation either. When measuring Java statistics, you need to clearly understand what we are measuring - the performance of the interpreter, the performance of non-optimized code, or the performance of optimized code. And it will turn out like in a joke, - “It doesn’t matter how they voted, it’s important how they felt.”

Instead of an epilogue.

Is this architecture a virtue or a disadvantage? Everyone will answer this question for himself, and everyone will be right. Java is able to solve all the tasks set before it, but you need to know well how it can do it and sometimes you have to compromise on something. But programmers like no one else know what the joy of creation is. The strongest motivator for the work of a programmer is the joy and satisfaction of contemplating the work of his work. Therefore, employers are so hard to motivate us with money. [1] We (at least most of us) love our work for the fact that the result of our work brings us joy, and at the same time, as a nice bonus, is still well paid. Therefore, we also love the tools that help us be happier and build creative relationships with our customers, colleagues and the community. Get joy from your work, be happy at work and you will not have to think about how to force yourself to do something. A person subconsciously strives for positive emotions and goes away from negative ones, so build positive creative relationships in your work and your hands will want to work themselves. If you do not get joy from your work, then you are doing something that is not something that you should. Do what makes you truly happy, do what you truly can - make the world a better place.

Be happy. Drink coffee. Write Java.

UPD: Corrected typos. Thank you so much Zeij for editing the text.

Source: https://habr.com/ru/post/122061/


All Articles