I'm trying to understand what the -XX:G1ReservePercent actually does. The descriptions I found in the official documentation are not really comprehensive:
Sets the percentage of reserve memory to keep free so as to reduce the risk of to-space overflows. The default is 10 percent. When you increase or decrease the percentage, make sure to adjust the total Java heap by the same amount.
and the desciption of to-space exhausted log entry is this:
When you see to-space overflow/exhausted messages in your logs, the G1 GC does not have enough memory for either survivor or promoted objects, or for both.
[...]
To alleviate the problem, try the following adjustments:
Increase the value of the
-XX:G1ReservePercentoption (and the total heap accordingly) to increase the amount of reserve memory for "to-space".[...]
Judging by the quote the to-space exhausted means that when performing mixed evacuation we do not have enough a free region to move survivors to.
But this then contradicts to the following official tuning advice in case of Full GC (emphasize mine):
Force G1 to start marking earlier. G1 automatically determines the Initiating Heap Occupancy Percent (IHOP) threshold based on earlier application behavior. If the application behavior changes, these predictions might be wrong. There are two options: Lower the target occupancy for when to start space-reclamation by increasing the buffer used in an adaptive IHOP calculation by modifying
-XX:G1ReservePercent;
So what is the buffer and what does setting -XX:G1ReservePercent do (From the first glance AdaptiveIHOP has nothing to do with it...) ?
Does it keep some heap space always reserved so when mixed evacuation occur we always have free regiong to move survivors to?
或者该空间用于G1内部管家任务?如果是这样,不清楚 to-space 包含哪些数据,所以它用完了?
对我来说,理解它的真正作用,意味着去源代码。我选择了jdk-15。
这个标志的最佳描述在这里:
它决定了我们应该在堆中拥有的最小储备,以最小化提升失败的概率。
太好了,所以这与“促销失败”(无论是什么)有关。但是按照你加粗的说法,这也有关系AdaptiveIHOP吗?嗯,是的,这个重要的参数仅在AdaptiveIHOP(这是在默认情况下)。
另外一点需要注意的是,G1ReservePercentage有没有保证要维持所有的时间,这是一个最大的努力。
如果您查看它在下一行中的使用方式:
if (_free_regions_at_end_of_collection > _reserve_regions) {
absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions;
}
Run Code Online (Sandbox Code Playgroud)
事情开始变得有意义了(对于那个大胆的声明)。注意如何_reserve_regions在提取了一些计算。G1将为“促销失败”保留该空间(我们会谈到这一点)。
如果G1保留该空间,则意味着可用于实际分配的空间更少。因此,如果您“增加此缓冲区”(G1ReservePercent正如引述所暗示的那样,您会变大),则用于放置新对象的空间会变小,因此GC需要启动的时间会更早,因此需要进行空间回收的时间将是也早点来(“降低目标占用率,以便开始空间回收......”)。这是一个复杂的句子,但用简单的话来说就是:
如果增加
G1ReservePercentage,则需要更快地回收空间(更频繁的 GC 调用)。
公平地说,这是显而易见的。并不是说我同意你应该增加那个价值,但这就是这句话所说的。
一定GC周期之后,是minor,mixed或者major,G1 知道有多少区域是免费的:
_free_regions_at_end_of_collection = _g1h->num_free_regions();
Run Code Online (Sandbox Code Playgroud)
这当然是“空闲列表”的长度:
return _free_list.length();
Run Code Online (Sandbox Code Playgroud)
基于这个值和_reserve_regions( G1ReservePercent) 加上目标暂停时间(200 ms默认情况下),它可以计算下一个周期需要多少个区域。到下一个周期结束时,可能会出现没有空区域的情况(或者空区域无法获取所有应该移动的活动对象)。Eden应该将活动对象 ( Survivor)移动到哪里,或者,如果old region是碎片化的 -活动对象应该移动到哪里进行碎片整理?这就是这个缓冲区的用途。
它充当安全网(代码中的注释使其更容易理解)。这是需要的,希望它能避免Full GC. 因为如果没有空闲区域(或足够多的区域)来移动活动对象,则需要进行 Full GC(很可能紧随其后young GC)。
当此消息出现在日志中时,通常认为该值很小。无论是增加了,还是很多更好的应用提供更多的堆。