Today, another dry day. This is the first in a series of the most hardcore JVMS on the web, starting with TLAB. Since the article is very long and everyone has different reading habits, it is hereby divided into single and multiple editions

  • TLAB Analysis of the most hardcore JVM in the web (single version does not include additional ingredients)
  • TLAB analysis of the most core JVM in the whole network 1. Introduction of memory allocation idea
  • TLAB analysis of the most core JVM in the entire network 2. TLAB life cycle and problem thinking
  • 3. JVM EMA expectation algorithm and TLAB related JVM startup parameters
  • 4. Complete analysis of TLAB basic process
  • Network most core JVM TLAB analysis 5 TLAB source code full analysis
  • 6. TLAB related hot Q&A summary
  • 7. Tlab-related JVM log parsing
  • 8. Monitor TLAB through JFR

6. The JVM expects to compute EMA

When designing the TLAB size mentioned above, we often talk about expectations. This expectation is calculated based on historical data, that is, each time the sample value is input, the latest expected value is obtained based on the historical sample value. This kind of expectation computation is used not only in TLAB, but also in JVM mechanisms such as GC and JIT. Here we look at an algorithm, EMA (Exponential Moving Average), which is often used in TLAB:

The core of EMA algorithm is to set an appropriate minimum weight. Let’s assume a scenario: Firstly, 100 samples of 100 are sampled (the first 100 samples in the algorithm are to eliminate unstable interference, so we directly ignore the first 100 samples here), then 50 samples of 2 are sampled, and the last 50 samples of 200 are sampled. For different minimum weights, look at the change curve.

It can be seen that the larger the minimum weight, the faster the change, the less affected by historical data. Setting the right minimum weight for your application can make your expectations even better.

The corresponding source code for this is the AdaptiveWeightedAverage class of Gcutil.hpp.

7. JVM parameters related to TLAB

It’s just listed here with a brief introduction. If you don’t understand it, there will be a detailed analysis to help you understand each parameter. The following parameters and default values are based on OpenJDK 17

7.1. TLABStats (Expired)

It has expired since Java 12, and there is no logic associated with it. Previously it was used for TLAB statistics to better scale TLAB but the performance cost was relatively high, but now it is mainly calculated through EMA.

7.2. UseTLAB

Note: Whether to enable TLAB, the default is enabled.

Default: true,

For example, if you want to close: -xx: -usetlab

7.3. ZeroTLAB

Note: whether to zero all bytes in the newly created TLAB. When we create a class, the field of the class has default values, such as Boolean is false, int is 0, etc., and the way to do that is to assign 0 to the allocated memory space. Setting ZeroTLAB to true means 0 is assigned when TLAB is requested, otherwise 0 is assigned when the object is allocated and initialized. Since TLAB Allocation involves allocating Prefetch to optimize the CPU cache, updating the Allocation of 0 immediately after TLAB is allocated should be more cache-friendly. Moreover, if TLAB is not full, Dummy Object is still a 0 array. In this case, open should be better. But ZeroTLAB is still disabled by default.

Default: false

For example: – XX: + ZeroTLAB

7.4. ResizeTLAB

Note: whether TLAB is variable, default is yes, that is, the expected TLAB size is calculated based on the EMA related to the thread history allocation data and the TLAB application is based on this size.

Default: true,

For example, if you want to close: -xx: -ResizetLab

7.5. TLABSize

Description: initial TLAB size. It’s in bytes

Default: 0, 0 is not active TLAB initial size, but through the JVM to calculate the initial size of each thread

For example: – XX: TLABSize = 65536

7.6. MinTLABSize

Description: minimum TLAB size. It’s in bytes

Default: 2048

For example: – XX: TLABSize = 4096

7.7. TLABAllocationWeight

TLAB initial size calculation is related to the number of threads, but threads are dynamically created and destroyed. Therefore, the TLAB size needs to be calculated by predicting the number of subsequent threads based on the number of historical threads. In general, a prediction function like this in a JVM uses EMA. This parameter is the minimum weight in Figure 06. The higher the weight, the greater the influence of the proportion of recent data. TLAB recalculates the size according to the allocation ratio, which also adopts EMA algorithm, and the minimum weight is TLABAllocationWeight

Default: 35

For example: – XX: TLABAllocationWeight = 70

7.8. TLABWasteTargetPercent

Description: TLAB size calculation involves the Eden zone size and the ratio of waste. TLAB waste refers to the space not allocated by the old TLAB when reapplying for a new TLAB mentioned above. This parameter is actually the percentage of Eden occupied by TLAB waste. The function of this parameter will be explained in detail in the following principle description

Default: 1.

Example: – XX: TLABWasteTargetPercent = 10

7.9. TLABRefillWasteFraction

Description: Initial Maximum Wasted Space limit calculated parameter, initial Maximum wasted space limit = current expected TLAB size/TLABRefillWasteFraction

Default: 64

Example: – XX: TLABRefillWasteFraction = 32

7.10. TLABWasteIncrement

Note: The maximum wasted space limit is not constant and increases when slow TLAB allocation occurs (i.e., when current TLAB space is insufficient to allocate). This parameter is the incremental TLAB waste allowed when TLAB is allocated slowly. The unit is not bytes, but the number of Markwords, which is the minimum unit of memory in the Java heap. In the case of a 64-bit virtual machine, the MarkWord size is 3 bytes.

Default: 4

Example: – XX: TLABWasteIncrement = 4