Escape analysis - compilation optimization technology (one of the most cutting-edge optimization techniques)

In Java, there are two typical cases where objects are no longer allocated on the heap: TLAB and stack allocation.

  • 1. Why not allocate on the heap
    We know that the heap is shared by all threads. In this case, it is a competing resource. For competing resources, necessary synchronization must be taken, so when using the new keyword to allocate objects on the heap, it is necessary to locked. Since there are locks, there must be overhead caused by locks, and since the entire heap is locked, the granularity of locks is relatively large. When objects are allocated frequently, it will inevitably affect the efficiency.

Therefore, for some special cases, it is possible to avoid allocating objects on the heap to improve the efficiency of object creation and destruction.

  • 2. TLAB allocation
    JVM opens up a small area in the new generation of memory Eden Space, which is privately owned by threads, called TLAB (Thread-local allocation buffer), and is set to occupy 1% of Eden Space by default. In Java programs, many objects are small objects and are thrown away after use. They are not shared by threads and are suitable for fast GC. Therefore, for small objects, the JVM usually allocates them on TLAB first, and the allocation on TLAB is thread-private. There is no locking overhead. So in practice it is usually more efficient to allocate multiple small objects than to allocate one large object.

  • That is to say, each thread in Java will have its own buffer called TLAB (Thread-local allocation buffer). Each TLAB has only one thread to operate. TLAB combined with bump-the-pointer technology can achieve fast object allocation , and does not need any locks for synchronization, that is, you do not need to lock the entire heap when objects are allocated, but only need to allocate in their own buffers.

  • 3. The escape analysis of the JVM allocated on the stack
    in the Server mode can analyze whether an object is always only within the scope of a certain method and thread, and does not "escape" out of this scope. One result of the escape analysis is that for some Unescaped objects can be allocated directly on the stack. Since the object must be local, there will be no problem with stack allocation.

  • Fourth, the idea and inspiration of
    object allocation on the heap The main reason why objects are not allocated on the heap is that the heap is shared, and there is the overhead of allocating locks on the heap. Both the TLAB and the stack are thread-private, which avoids competition (of course, additional problems such as visibility problems may occur), which is a typical practice of exchanging space for efficiency.
    In practice, there are many similar practices. For example, in Hadoop, the Map process is processed in the local memory of the node, and the data is merged until the last Reduce process. For tasks that can be decomposed into different threads and processes, a similar approach can be used to exchange space for efficiency, which is of great help in improving throughput.

JVM just-in-time compiler (late) optimization techniques: common subexpression elimination, array range check elimination, method inlining, escape analysis reference runtime optimization . Escape analysis is the main topic here.

1. Escape analysis:

The basic behavior of escape analysis is: analyze the dynamic scope of objects: when an object is defined in a method, it may be referenced by external methods, and the composition parameters are passed to other methods, which is called: method escape. Or accessed by a thread, which is called thread escape. And if an object does not escape outside the method or thread. That is, other methods cannot access this object in any way, and this object or variable can be optimized efficiently.

Escape analysis is a cross-function global data flow analysis algorithm that can effectively reduce synchronization load and memory heap allocation pressure in Java programs

Optimization:

The compiler can use the results of escape analysis to optimize the program.

  1. Heap-allocated objects become stack-allocated objects. If the object reference in a method does not escape, the method may be allocated on the stack memory instead of the common heap memory.

  2. Remove sync. The cost of thread synchronization is quite high, and the consequences of synchronization are reduced concurrency and performance. Escape analysis can determine whether an object is always accessed by only one thread. If it is accessed by only one thread, then the synchronization operation of the object can be converted into an operation without synchronization protection, which can greatly improve the degree of concurrency and performance.

  3. Vector alternative. In the escape analysis method, if it is found that the memory storage structure of the object does not need to be continuously performed, part or even all of the object can be stored in the CPU register, which can greatly improve the access speed.

2.TLAB

The JVM has opened up a small thread-private area in the new memory generation Eden Space, called TLAB (Thread-local allocation buffer). The default setting is to occupy 1% of Eden Space. In Java programs, many objects are small objects and are thrown away after use. They are not shared by threads and are suitable for fast GC. Therefore, for small objects, the JVM usually allocates them on TLAB first, and the allocation on TLAB is thread-private. There is no locking overhead. So in practice it is usually more efficient to allocate multiple small objects than to allocate one large object.
That is to say, each thread in Java will have its own buffer called TLAB (Thread-local allocation buffer). Each TLAB has only one thread to operate. TLAB combined with bump-the-pointer technology can achieve fast object allocation , and does not need any locks for synchronization, that is, you do not need to lock the entire heap when objects are allocated, but only need to allocate in their own buffers.

3. The process of Java object allocation

  1. The compiler uses escape analysis to determine whether an object is allocated on the stack or on the heap. If allocated on the heap, go to option 2.

  2. If tlab_top + size <= tlab_end, directly allocate the object on TLAB and increase the value of tlab_top, if the existing TLAB is not enough to store the current object then 3.

  3. Reapply for a TLAB and try to store the current object again. If you can't put it down, then 4.

  4. Lock in the Eden area (this area is shared by multiple threads), if eden_top + size <= eden_end, store the object in the Eden area, increase the value of eden_top, if the Eden area is not enough to store, then 5.

  5. Perform a Young GC (minor collection).

  6. After Young GC, if the Eden area is still not enough to store the current object, it will be directly allocated to the old generation.

Original link

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324378535&siteId=291194637