Introduction to the

Escape analysis, which we covered in JVM Performance Tuning in JDK14, results in the JVM allocating objects on the stack to improve efficiency. If we are in a multi-threaded environment, how can we improve the efficiency of memory allocation? Come and learn TLAB technology with your junior sister.

Escape analysis and on-stack allocation

Brother F, it used to be said that objects were allocated in the heap, and THEN I believed it. Last time you said that you could allocate objects on the stack, which really changed my understanding.

Plato said: Thought is always the ruler of the universe. As long as the mind does not slide, the method is more than difficult. What people tell you is the most basic, most generic information. And what I tell you is the special case in the optimization.

Brother F, it seems that the JVM has really made a lot of optimizations to improve the running speed.

Yeah, Java has been criticized for being slow from the beginning, but now it’s almost as fast as C. These runtime optimizations are essential. Remember when we talked about escape analysis?

Small pool: F brother, this I know, if an object is inside the method of distribution, and the absence of multithreaded access, then the object can be seen as a local object, actually such objects regardless of where to create visible only to this thread in this method, thus can be directly allocated in the stack space.

Yes, stack-allocated objects execute faster because they don’t have to worry about synchronization, which is why the JVM introduced stack-allocated objects.

Let me give you another visual example. To build a Car, a factory creates a Car object and then wheels it.

  public static void main(String[] args) {
    buildCar();
  }
  public static void buildCar(a) {
    Wheel whell = new Wheel(); // Assign wheels
    Car car = new Car(); // Assign carscar.setWheel(whell); }}class Wheel {}

class Car {
  private Wheel whell;
  public void setWheel(Wheel whell) {
    this.whell = whell; }}Copy the code

Consider the case above, if the workshop is a robot assembling a Car, then the Car and Wheel objects created in the above method will only be accessed by this robot, and the other robots will not use the Car object at all. So this object is essentially invisible to other robots. So we can allocate this object not in public space, but in private stack space.

Another function of escape analysis is lock Coarsening. Similarly, in a single-threaded environment, locks are not needed and can be optimized.

TLAB profile

Brother F, I think escape analysis is very good, and stack allocation is also good. Why use TLAB when these two technologies are so awesome?

First, these are two different concepts. TLAB stands for Thread-local Allocation Buffers. Threadlocal is a Local variable of a Thread. TLAB is the thread’s local allocation of space.

Escape analysis and on-stack allocation only compete in a single-threaded environment. In a multi-threaded environment, it is inevitable that multiple threads will simultaneously allocate objects in the heap space.

What can be done to improve performance in this case?

Wow, multiple threads competing for shared resources. Isn’t this a typical locking and synchronization problem?

Locking and synchronization are designed to ensure that the entire resource can only be accessed by one thread at a time, and we now have a situation where threads are allocated areas within the resource. This operation does not require complete synchronization because the heap space is large enough that we can divide the space into small chunks for each thread. Doesn’t that solve the synchronization problem? This could also be called space for time.

TLAB,

Remember the one center and two basic points in heap generation? Oh, one Eden Space and two Suvivor Space?

Young Gen is divided into 1 Eden Space and 2 Suvivor Space. When the object is first created, it is placed in Eden Space. Eden Space and a Suvivor Space are scanned for garbage collection. If an object in Eden Space is found to be valid at garbage collection time, it will be copied to another Suvivor Space.

In this way, the objects that are still valid will be put into Old Gen after multiple scans, indicating that their life cycle is relatively long and garbage collection time can be reduced.

Since TLAB focuses on newly allocated objects, it is allocated in Eden interval. As can be seen from the figure, TLabs are continuous Spaces one by one.

The contiguous space is then allocated to individual threads.

Since each thread has its own separate space, the concept of synchronization is not involved here. TLAB is enabled by default and you can use:

-XX:-UseTLAB
Copy the code

To shut it down.

Set the TLAB space size

Junior sister, brother F, is the size of this TLAB set by the system by default? Can we manually control its size?

To solve this problem, we still have to go to the c + + implementation of the JVM, namely threadLocalAllocBuffer. CPP:

As you can see from the code above, if TLAB is set (the default is 0), then the size of TLABSize is the smallest of the defined TLABSize divided by HeapWordSize and max_size().

HeapWordSize is the size of a word in the heap, which I guess =8. Don’t ask me why, in fact, I guess, if anyone knows the answer can leave me a comment.

TLAB size can be obtained by:

-XX:TLABSize
Copy the code

To set up.

If the TLAB is not set, the TLAB size is the average of the allocated threads.

TLAB minima can be obtained by:

-XX:MinTLABSize
Copy the code

To set up.

By default:

-XX:ResizeTLAB
Copy the code

The resize switch is turned on by default, so the JVM can adjust the TLAB space size.

Allocation of large objects in TLAB

F: Brother F, I have a question: since TLAB has size, if a thread defines a very large object, TLAB can not fit, what should be done?

Good question. In this case, there are two possibilities. Let’s assume that the size of the TLAB is now 100K:

The first possibility:

At present, TLAB has been used for 20K and still has 80K size left. At this time, we create a 90K size object. Now, the 90K size object cannot fit into TLAB, so we need to allocate the object directly in the heap space.

Second possibility:

The TLAB is currently 90K in use, with 10K remaining, so we create a 15K object.

At this point, consider whether to continue slow Allocation.

Since the TLAB has almost run out, the JVM can try to make sure that new objects will still have a TLAB available later, and then allocate a new TLAB space and put 15K objects in it.

The JVM has a switch called:

-XX:TLABWasteTargetPercent=N
Copy the code

The default value of this switch is 1. Indicates that if the size of the newly allocated object exceeds the set size, slow allocation will be performed. Otherwise a new TLAB space will be allocated.

The JVM also defines a switch:

-XX:TLABWasteIncrement=N
Copy the code

To prevent excessive slow allocation, the JVM defines this switch (the default is 4). For example, if the limit for the first slow allocation is 1%, then the limit for the next slow allocation is %1+4%=5%.

Waste in TLAB space

Brother F, if the new TLAB space is allocated, what about the unused space in the old TLAB?

This is called TLAB Waste. Since objects are no longer allocated in the old TLAB space, the remaining space is wasted.

conclusion

This paper introduces escape analysis and the use of TLAB. I hope you enjoy it.

Author: Flydean program stuff

Link to this article: www.flydean.com/jvm-escapse…

Source: Flydean’s blog

Welcome to pay attention to my public number: procedures those things, more wonderful waiting for you!