Most of the performance problems in JAVA development are not caused by the JAVA language itself, but by the programs we write in those languages, so it is important to develop good coding habits.

Here are some typical cases that are common in daily development:

Internal methods in a class are declared private

When writing code, you like all methods in a class to be public (for reasons we all know).

For methods that do not require external access to be made private, not only because of object-oriented thinking, data encapsulation and secure access principles, but also because any private method is implicitly final!

Any private methods in a class are implicitly final.

Think In Java

From Chapter 6 of Think In Java

Methods decorated with final can increase the possibility of inline

Method inlining is the process of “copying” the caller’s function code into the caller’s function and executing it as part of its own code to reduce the overhead caused by function calls, i.e. JIT optimization.

The pseudocode is as follows:

public int sum(int a, int b, int c, int d){
    return add1(a, b) + add2(c, d);
}

private int add1(int a, int b){
    return a + b;
}

private int add2(int c, int d){
    return c + d;
}
Copy the code

Inline code:

public int sum(int a, int b, int c, int d){
    return a + b + c + d;
}
Copy the code

Why does method inlining improve performance?

Everyone knows the function call is actually to the operation of the stack stack, namely the pressure and the stack process, when a method is invoked, a new stack frame will be added to the stack, the distribution of local variables and parameters are stored in the stack frame, and then jump to the target method code execution, the method returns, the local method and parameters is destroyed, the stack is removed, Finally return to the original address to execute.

Therefore, function calls need to have a certain amount of time and space overhead, when a method body is not large, but is frequently called, this time and space overhead will become relatively large, so it becomes very uneconomical, is bound to reduce the performance of the program. According to the 80/20 principle, 80% of the performance consumption actually occurs in 20% of the code, and targeted optimization of hot code can improve the overall system performance.

Methods can be inlined conditionally. You can use JVM parameters -xx :CompileThreshold and -xx :MaxFreqInlineSize to determine the size of the inlined method body.

So the business scenarios where method inlining can be used are:

Final is recommended for frequently invoked hot methods that are small in size. (Private methods implicitly specify a final modifier, so you do not need to specify a final modifier for them.)

The public method also recommends specifying the final modifier as much as possible

Based on the first article above, the method that meets the above business scenario is for the same reason as above, which is conducive to JIT optimization. Final classes are not allowed to be inherited, and all methods in that class are final by default.

There is one additional qualification: there are no methods propped up by Spring AOP

Don’t implement anonymous inner classes where lambda expressions can be used

Lambda expressions are more than just syntactic candy. The compiled class file executes instructions in the JVM differently, using invokeDynamic, which is less expensive than calls to anonymous inner classes because it does not have the initialization process of anonymous inner classes and is simpler in code.

Anonymous inner class:

private static final ExecutorService thredPool = Executors.newCachedThreadPool(); Thredpool.submit (new Runnable() {@override public void run() {// business logic}});Copy the code

Lambda expression:

private static final ExecutorService thredPool = Executors.newCachedThreadPool(); Thredpool.submit (() -> {// business logic});Copy the code

Try not to call global variables too often in methods

In class, the member variables (global variable) stored in the Heap Heap, function within the local variables (basic type, parameters, object references) are stored in the Stack Stack, inside the function to access their own these variables must be faster than external variable speed access function, so from the Stack operation speed will be slow in the Heap data.

Example code is as follows (counter example) :

private int result = 0; Public void sum(int... i){ for (int j : i) { result += j; Result}}Copy the code

Modified code:

private int result = 0; Public void sum(int... i){ int temp = 0; For (int j: I) {temp += j; } result = temp; // Reduce access to member variables}Copy the code

Optimize the set operation in the first contains and then get writing method

In our code, we often encounter business scenarios to determine whether this element exists in the set and re-value it. The pseudo-code is as follows:

public void setOrderPrice(Order order, Map<String, Price> map){ if(map.containsKey(order.getId())){ order.setPrice(map.get(order.getId())); } else { order.setPrice(new Price()); }}Copy the code

In fact, you can call get directly and declare null, which saves the process of searching for a match, modify as follows:

public void setOrderPrice(Order order, Map<String, Price> map){ Price price = map.get(order.getId(); // Get if(price! = null){ order.setPrice(price); } else { order.setPrice(new Price()); }}Copy the code

These are just some of the insights that the author has been working on over the years in terms of Java development performance. Performance optimization requires trade-offs in terms of time, efficiency, and readability. Don’t take the above content as a guideline.

Source: javakk.com/197.html