Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to optimize the unused space in the Java heap

Tags:

Do not take my word on this. I am just repeating what I have pieced together from different sources. HotSpot JVM uses Thread Local Allocation Buffers (TLABs). TLABs can be synchronized or not. Most of the time the TLABs are not synchronized and hence a thread can allocate very quickly. There are a large number of these TLABs so that the active threads get their own TLABs. The less active threads share a synchronized TLAB. When a thread exhausts its TLAB, then it gets another TLAB from a pool. When the pool runs out of TLABs, then Young GC is triggered or needed.

When the pool runs out of TLABs, there are still going to be TLABs with space left in them. This "unused space" adds up and is significant. One can see this space because GC is triggered before the reserved heap size or the max heap size is reached. Thus, the heap is effectively 10-30% smaller. At least that is my guess from looking at heap usage graphs.

How do I tune the JVM to reduce the unused space?

like image 867
Nathan Avatar asked Aug 10 '17 12:08

Nathan


2 Answers

You can tweak that setting with the command-line option -XX:TLABSize

However as with most of these "deep down and dirty" settings, you should be very careful when changing those and monitor the effect of your changes closely.

like image 135
TwoThe Avatar answered Sep 20 '22 20:09

TwoThe


You are correct that once there are no TLABs, there will be a young generation collection and they will be cleaned.

I can't tell much, but there is ResizeTLAB that allows for the JVM to resize it based on allocations stats I guess, eden size, etc. There's also a flag called TLABWasteTargetPercent (by default it is 1%). When the current TLAB can not fit one more object, JVM has to decide what to do : allocate directly to the heap, or allocate a new TLAB.

If this objects size is bigger than 1% of the current TLAB size it is allocated directly; otherwise the current TLAB is retired.

So let's say current size of the TLAB (TLABSize, by default it is zero, meaning it will be adaptive) is 100 bytes (all numbers are theoretical), 1% of that is 1 byte - that's the TLABWasteTargetPercent. Currently your TLAB is filled with 98 bytes and your object that you want to allocate is 3 bytes. It will not fit in this TLAB and at the same time it is bigger than 1 byte threshold => it is allocated directly on the heap.

The other way around is that your TLAB is full with 99.7 bytes and you try to allocate a 1/2 byte object - it will not fit; but it is smaller than 1 byte; thus this TLAB is committed and a new one is given to you.

As far as I understand, there is one more parameter called TLABWasteIncrement - when you fail to allocate in the TLAB (and allocate directly in the heap) - so that this story would not happen forever, the TLABWasteTargetPercent is increased by this value (default of 4%) increasing the chances of retiring this TLAB.

There is also TLABAllocationWeight and TLABRefillWasteFraction - will probably update this post a bit later with them

like image 35
Eugene Avatar answered Sep 23 '22 20:09

Eugene