GC pessimistic strategy-Parallel GC

Source: Internet
Author: User

Let's take a look at the code section:
Java code
Import java. util .*;
Public class SummaryCase {
Public static void main (String [] args) throws Exception {
List <Object> caches = new ArrayList <Object> ();
For (int I = 0; I <7; I ++ ){
Caches. add (new byte [1024*1024*3]);
}
Caches. clear ();
For (int I = 0; I <2; I ++ ){
Caches. add (new byte [1024*1024*3]);
}
Thread. sleep (10000 );
}
}
How many times will Minor GC and Full GC be executed when I use-Xms30m-Xmx30m-Xmn10m-XX: + UseParallelGC to execute the above Code?
According to the Rules that trigger the minor gc when the eden space is insufficient, the GC after the above code execution should be: M, but in fact the GC after the above code execution is: m, F, F.
This is because of the pessimistic policy of Parallel Scavenge GC. When the allocation of memory on eden fails and the object size does not need to be allocated directly on the old, YGC is triggered, the code snippet is as follows:
Cpp Code
Void PSScavenge: invoke (){
...
Bool scavenge_was_done = PSScavenge: invoke_no_policy ();
PSGCAdaptivePolicyCounters * counters = heap-> gc_policy_counters ();
If (UsePerfData)
Counters-> update_full_follows_scavenge (0 );
If (! Scavenge_was_done | policy-> should_full_GC (heap-> old_gen ()-> free_in_bytes ())){
If (UsePerfData)
Counters-> update_full_follows_scavenge (full_follows_scavenge );
<GCCauseSetter gccs (heap, GCCause: _ adaptive_size_policy );
If (UseParallelOldGC ){
PSParallelCompact: invoke_no_policy (false );
} Else {
PSMarkSweep: invoke_no_policy (false );
}
}
...
}
PSScavenge: invoke_no_policy {
...
If (! Should_attempt_scavenge ()){
Return false;
}
...
}
Bool PSScavenge: should_attempt_scavenge (){
...
PSAdaptiveSizePolicy * policy = heap-> size_policy ();
Size_t avg_promoted = (size_t) policy-> padded_average_promoted_in_bytes ();
Size_t promotion_estimate = MIN2 (avg_promoted, young_gen-> used_in_bytes ());
Bool result = promotion_estimate <old_gen-> free_in_bytes ();
...
Return result;
}
In the should_attempt_scavenge code snippet above, we can see that the average size of the previously promoted YGC to Old is compared with the byte size that has been used in the current new generation, compare the smaller value with the remaining space of the old generation. If the value is larger, false is returned, and YGC execution is terminated. When false is returned, PSScavenge :: invoke will trigger Full GC.
In PSScavenge: invoke, another condition is: policy-> should_full_GC (heap-> old_gen ()-> free_in_bytes (). Let's take a look at this code snippet:
Cpp Code
Bool PSAdaptiveSizePolicy: should_full_GC (size_t old_free_in_bytes ){
Bool result = padded_average_promoted_in_bytes ()> (float) old_free_in_bytes;
...
Return result;
}
We can see that this code checks whether the average size of the previous YGC promotion to old is greater than the remaining space of the old generation. If it is greater than, the full gc is triggered.
Summary of the analysis above, we can see that when Parallel GC is used, when YGC is triggered, there will be two checks:
1. Before YGC execution, min (the current size of the new generation, which is smaller than the average size of the old generation)> what is the remaining space of the old generation? Execute Full GC directly without executing YGC: Execute YGC;
2. After YGC is executed, the average size is promoted to the old size> the remaining space of the old generation? Trigger Full GC: do nothing.
 
Let's take a look at the changes in eden and old sizes during the execution of the above Code:

 

Code

Eden

Old

YGC

FGC

First cycle

3

0

0

0

Second Cycle

6

0

0

0

The third cycle

3

6

1

0

Fourth Cycle

6

6

1

0

Fifth Cycle

3

12

2

0

Sixth cycle

6

12

2

0

Seventh cycle

3

18

3

1

Eighth cycle

6

18

3

1

Ninth cycle

3

3

3

2

In the first cycle, the remaining space of the old generation after YGC is 2 m, and the size of the object that has been upgraded to the old is 6 m on average. Therefore, a FGC is triggered after YGC.
In 9th cycles, before YGC was executed, the size of the new generation was 6 m, and the average size of the old generation was 6 m, and the minimum value of the two was 6 m, this value is greater than the remaining space of old, so YGC is not executed and FGC is executed directly.

 

Sun JDK has a pessimistic strategy. I guess the reason is that the program will eventually be executed in a relatively steady state. At this time, every time YGC is promoted to an old object, the size of the object should be similar, check YGC to prevent the Old space from being insufficient due to the objects that are later upgraded to old by YGC. Therefore, it is better to directly execute FGC because of the existence of pessimistic policies, sometimes you may see that the old space is not full but full gc is executed.

 

Author "lewis @ Taobao"
 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.