Concept is introduced

We all know that objects created in Java are allocated to the heap, but this is not always the case. By analyzing the process of Java object allocation, we can see that there are two places where objects created in Java are not necessarily allocated to the heap. These two points are the escape analysis in Java and the TLAB (Thread Local Allocation Buffer) Thread private cache area.

Introduction to Basic Concepts

Escape analysis is a cross-function global data flow analysis algorithm that can effectively reduce the synchronization load and memory heap allocation pressure in Java programs. Through escape analysis, the Java Hotspot compiler can figure out how far a new object’s references are used to determine whether to allocate the object to the heap.

In the compiler optimization principle of computer language, escape analysis refers to the method of analyzing the dynamic range of pointer, which is related to the pointer analysis and shape analysis of compiler optimization principle. When a variable (or object) is allocated in a method, its pointer may be returned or referenced globally, and thus referenced by other procedures or threads. This phenomenon is called pointer (or reference) Escape. In layman’s terms, an object’s pointer is said to have escaped when it is referenced by multiple methods or threads.

The escape analysis option is supported and enabled by default in Java SE 6U23 and later. Java’s HotSpot JIT compiler can perform escape analysis on code when a method is overloaded or dynamically loaded, while Java objects are allocated on the heap and built-in threads make escape analysis an important feature of Java.

Code sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package
me.stormma.gc;
/ * *

* <p>Created on 2017/4/21.</p>

*

* @author stormma

*

* @title <p> Escape analysis </p>

* /
public
class
EscapeAnalysis {

public
static
B b;

/ * *

* <p> Global variable assignment occurs pointer escape </p>

* /

public
void
globalVariablePointerEscape() {

b =
new
B();

}

/ * *

* <p> method returns reference, pointer escape occurs </p>

* @return

* /

public
B methodPointerEscape() {

return
new
B();

}

/ * *

* <p> Instance reference pointer escape </p>

* /

public
void
instancePassPointerEscape() {

methodPointerEscape().printClassName(
this
);

}

class
B {

public
void
printClassName(EscapeAnalysis clazz) {

System.out.println(clazz.getClass().getName());

}

}
}

What are the benefits of escape analysis research for the Java compiler? We know that Java objects are always allocated in the heap, so the creation and recycling of Java objects can be very expensive to the system. One of the criticisms of the Java language, and one of the reasons for Java’s slow performance, is that Java does not support allocating objects on the stack. The Swing memory and performance bottleneck in JDK6 is due to the GC iterating through the reference tree and reclaiming memory. If the number of objects is large, the GC will be put under a lot of pressure, which indirectly affects performance. Reducing the number of temporary objects allocated in the heap is undoubtedly the most efficient optimization method. In Java application in a widespread scenes, usually in the method, declare a local variable, and the variable in a method implementation life cycle, there was no escape, according to the JVM memory allocation mechanism, first on the heap memory to create instances of the class (object), then press the object reference into the call stack, continue to perform, This is the way the JVM was before optimization. Of course, we can use escape analysis to optimize the JVM. Namely for the redistribution of the stack, first we need to analyze and find the variables did not escape, the variable class instantiation memory allocated in the stack directly, without having to enter the heap, distribution is completed, continue to run the call stack, the last end of the thread, stack space are recycled, local variable object also be recycled, optimization in this way, The main difference lies in the storage medium of the object. The object before optimization is in the heap, while the object after optimization is in the stack, thus reducing the allocation of temporary objects in the heap (time-consuming), thus optimizing the performance.

Performance optimization using escape analysis (-xx :+DoEscapeAnalysis turns on escape analysis)

1
2
3
4
5
6
public
void
method() {

Test test =
new
Test();

// Process logic

.

test =
null
;
}

This code can allocate memory on the stack because there is no pointer escape, that is, the reference does not expose the method body.

Stack and heap memory allocation comparison

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package
me.stormma.gc;
/ * *

* <p>Created on 2017/4/21.</p>

*

* @author stormma

* @description: <p> Memory allocation comparison </p>

* /
public
class
EscapeAnalysisTest {

public
static
void
alloc() {

byte
[] b =
new
byte
[
2
];

b[
0
] =
1
;

}

public
static
void
main(String[] args) {

long
b = System.currentTimeMillis();

for
(
int
i =
0
; i <
100000000
; i++) {

alloc();

}

long
e = System.currentTimeMillis();

System.out.println(e - b);

}
}

The JVM parameter is -server-XMx10m-xMS10M-xx: -doEscapeAnalysis -xx :+PrintGC, and the result is run

The JVM parameter is -server-XMx10m-xMS10m-xx :+DoEscapeAnalysis -xx :+PrintGC, and the result is displayed

The performance test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package
me.stormma.gc;
/ * *

* <p>Created on 2017/4/21.</p>

*

* @author stormma

*

* @description: <p> Performance optimization using escape analysis </p>

* /
public
class
EscapeAnalysisTest {

private
static
class
Foo {

private
int
x;

private
static
int
counter;

public
Foo() {

x = (++counter);

}

}

public
static
void
main(String[] args) {

long
start = System.nanoTime();

for
(
int
i =
0
; i <
1000
*
1000
*
10
; ++i) {

Foo foo =
new
Foo();

}

long
end = System.nanoTime();

System.out.println(
"Time cost is "
+ (end - start));

}
}

Optimize JVM output using escape analysis (-server-xx :+DoEscapeAnalysis -xx :+PrintGC)

1
Time cost is
11012345

Optimized JVM output without escape analysis (-server-XMx10m-xMS10m-xx: -doEscapeAnalysis -xx :+PrintGC)

1
2
3
4
5
[GC (Allocation Failure) 33280K->408K(125952K),
0.0010344
secs]
[GC (Allocation Failure) 33688K->424K(125952K),
0.0009799
secs]
[GC (Allocation Failure) 33704K->376K(125952K),
0.0007297
secs]
[GC (Allocation Failure) 33656K->456K(159232K),
0.0014817
secs]
Time cost is
68562263

Analysis results, performance optimization 1/6.


From: www.importnew.com/27262.html