-
Bug
-
Resolution: Unresolved
-
P4
-
14
Use of small values of EpsilonMaxTLABSize results in too small actual TLAB sizes.
E.g. logging in ThreadLocalAllocBuffer::initial_desired_size() around determining the TLAB size:
log_error(gc, tlab)("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT,
min_size(), init_sz, max_size());
init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
log_error(gc, tlab)("result size " SIZE_FORMAT, init_sz);
and running a HelloWorld with
~/Downloads/vmshare/jdk10/hs/build/linux-x64-debug/images/jdk/bin/java -XX:+UnlockExperimentalVMOptions -XX:EpsilonMaxTLABSize=1 -XX:+UseEpsilonGC HelloWorld
results in this output:
[0.008s][error ][gc,tlab] TLAB min: 328 initial: 5270046 max: 256
[0.008s][error ][gc,tlab] result size 256
I.e. the used TLAB is too small, potentially so small (with larger reserve for allocation prefetch) so that it can't contain any object.
E.g. $java -XX:AllocatePrefetchDistance=512 -XX:AllocatePrefetchLines=64 -XX:MinTLABSize=4736 -XX:+UnlockExperimentalVMOptions -XX:EpsilonMaxTLABSize=1 -XX:+UseEpsilonGC HelloWorld
Gives:
[0.007s][error ][gc] allocation-prefetch 592 // the reserve for allocation prefetch
[0.007s][error ][gc,tlab] TLAB min: 1184 initial: 5270046 max: 592
[0.007s][error ][gc,tlab] result size 592
This disables TLABs effectively afaict.
Other collectors are not affected afaict: their (calculated) maximum TLAB size is always much larger than the reserve.
The other problem is that withJDK-8233702 the code will assert and fail the VM, because the introduced check in the "init_sz" calculation
init_sz = clamp(init_sz, min_size(), max_size());
will notice that ThreadLocalAllocBuffer::max_size() < ThreadLocalAllocBuffer::min_size().
The reason for this failure is some initialization code in epsilonArguments.cpp:
if (EpsilonMaxTLABSize < MinTLABSize) {
log_warning(gc)("EpsilonMaxTLABSize < MinTLABSize, adjusting it to " SIZE_FORMAT, MinTLABSize);
EpsilonMaxTLABSize = MinTLABSize;
}
and initialization of ThreadLocalBuffer::max_size() in epsilonHeap.cpp:
_max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), align_object_size(EpsilonMaxTLABSize / HeapWordSize));
(_max_tlab_size is later used to set ThreadLocalAllocBuffer::max_size() directly)
E.g. logging in ThreadLocalAllocBuffer::initial_desired_size() around determining the TLAB size:
log_error(gc, tlab)("TLAB min: " SIZE_FORMAT " initial: " SIZE_FORMAT " max: " SIZE_FORMAT,
min_size(), init_sz, max_size());
init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
log_error(gc, tlab)("result size " SIZE_FORMAT, init_sz);
and running a HelloWorld with
~/Downloads/vmshare/jdk10/hs/build/linux-x64-debug/images/jdk/bin/java -XX:+UnlockExperimentalVMOptions -XX:EpsilonMaxTLABSize=1 -XX:+UseEpsilonGC HelloWorld
results in this output:
[0.008s][error ][gc,tlab] TLAB min: 328 initial: 5270046 max: 256
[0.008s][error ][gc,tlab] result size 256
I.e. the used TLAB is too small, potentially so small (with larger reserve for allocation prefetch) so that it can't contain any object.
E.g. $java -XX:AllocatePrefetchDistance=512 -XX:AllocatePrefetchLines=64 -XX:MinTLABSize=4736 -XX:+UnlockExperimentalVMOptions -XX:EpsilonMaxTLABSize=1 -XX:+UseEpsilonGC HelloWorld
Gives:
[0.007s][error ][gc] allocation-prefetch 592 // the reserve for allocation prefetch
[0.007s][error ][gc,tlab] TLAB min: 1184 initial: 5270046 max: 592
[0.007s][error ][gc,tlab] result size 592
This disables TLABs effectively afaict.
Other collectors are not affected afaict: their (calculated) maximum TLAB size is always much larger than the reserve.
The other problem is that with
init_sz = clamp(init_sz, min_size(), max_size());
will notice that ThreadLocalAllocBuffer::max_size() < ThreadLocalAllocBuffer::min_size().
The reason for this failure is some initialization code in epsilonArguments.cpp:
if (EpsilonMaxTLABSize < MinTLABSize) {
log_warning(gc)("EpsilonMaxTLABSize < MinTLABSize, adjusting it to " SIZE_FORMAT, MinTLABSize);
EpsilonMaxTLABSize = MinTLABSize;
}
and initialization of ThreadLocalBuffer::max_size() in epsilonHeap.cpp:
_max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), align_object_size(EpsilonMaxTLABSize / HeapWordSize));
(_max_tlab_size is later used to set ThreadLocalAllocBuffer::max_size() directly)