Friday, September 9, 2016

G1GC in depth

FAQ

 1. When is the GC triggered?

gc is triggered when allocating heap for an object/objects fails.  

 2. When is the Mixed GC is triggered?

If the heap occupancy after gc is higher than certain threshold (defined by InitiatingHeapOccupancyPercent), a mixed gc cycle is triggered.
The mixed gc cycle starts with initial marking, which is piggy-backed on a young gc.
After initial marking, g1 will do concurrent mark, remark and clean up.  It is likely you will see several young gcs between the marking cycles.
Before starting a mixed gc, g1 will check if the reclaimable heap is over a certain threshold.  This threshold is defined by -XX:G1HeapWastePercent.  The reclaimable is calculated by checking how much can be reclaimed from the candidate (old) regions.  If the reclaimable is higher than the waste threshold, a mixed gc cycle will start.
Here is what I meant by candidate regions: After marking, the old regions are sorted by the occupancy for the regions.  If the occupancy of a region is lower than a threshold (defined by experimental flag -XX:G1MixedGCLiveThresholdPercent=<85>), this region is considered as a candidate region.
After each mixed gc, g1 will check if the reclaimable heap is over the wasted threshold.  If it is, it will continue with another mixed gc.

 3. How different types of references are handled during gc?

We are talking about the weak references in general, which includes SoftReference, WeakReference, FinalReference, PhantomReference, and JNI Weak Reference.
G1 has 2 reference processors: stop the world (_ref_processor_stw) and concurrent_marking (_ref_processor_cm). _ref_processor_stw is used during STW pauses(young/mixed/full gc) ; _ref_processor_cm is used during concurrent marking.  These 2 both span the heap.
During a STW pause, _ref_processor_cm discovery is temporally disabled.  _ref_processor_stw handles the reference object discovery and processing.  At the end of the evacuation, _ref_processor_stw process the discovered references and en queue the rest.  _ref_processor_cm discovery is restored.
ref_processor_cm handles reference object discovery and processing during the concurrent marking cycle.  The discovery is enabled during initial-marking.  The reference is processed during remark.
Tuning related parameters:
-XX: SoftRefLRUPolicyMSPerMB=<1000>: This defines how long the softly reachable objects will remain alive after they were referenced. The default is 1000ms per free MB in heap.
-XX:+ParallelRefProcEnabled: This enables parallel reference processing.

 4. What are the threads involved in GC?


 Name  Parameters   function
 ParallelGC Thread   -XX:ParallelGCThreads  parallel work during gc
 Parallel Marking Threads   -XX:ConcGCThreads   parallel threads for concurrent marking
 G1 concurrent refinement Threads  -XX:G1ConcRefinementThreads  update RSet concurrently with the application

 5. What is TLAB?  How is this related to GC performance?

TLAB is thread local allocation buffer.  Each thread has it's thread local buffer for allocation.  Only when a thread runs out of local buffer, it goes to the global area for a new buffer.  This helps reducing contention allocating heap for objects.  
Too small TLAB hurts the performance as there is too much contention.  Too big TLAB can have more heap wasted.

 6. What is Code Cache?  Is it related to GC performance?

 7. Is there any flags to restrict the gc pause time, regardless of the GC policies?

You can start with -XX:MaxGCPauseMillis,  However, this is a soft goal.  G1 will try to meet this goal, but there is no guarantee.  Especially for mixed gc.  Additional tuning is needed.

 8. What is 'to-space exhausted'?  Why it is slow? How to avoid it?

'to-space exhausted' happens when there is not enough space to copy to during evacuation.  It is slow because g1 has to do a lot of work to make sure the heap is in a ready-to-use state.  There are several ways you can try to avoid it.  Trigger the mixed gc earlier by decreasing -XX:InitiatingHeapOccupancyPercent (default 45), adjust Young Gen size, increase G1ReservePercent, give larger heap headroom, etc.  There is no one size fits all tuning.

9. What is the recommended way to limit Eden size for g1?

 The recommended way is to set  -XX:MaxGCPauseMillis.  G1 will adjust YoungGen size trying to meet the pause goal.  The Young gen size is between 5 to 60 percent of the heap size.  To control it further, you can use Experimental flags:
-XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=<5> -XX:G1MaxNewSizePercent=<60>.
 G1 will pick up other settings, such as NewRatio, NewSize, MaxNewSize, -Xmn
-Xmn: the same as NewSize=MaxNewSize
only -XX:NewSize is set, the young gen size is between specified NewSize and  G1MaxNewSizePercent
only -XX:MaxNewSize is set, the young gen size is between specified G1NewSizePercent and MaxNewSize.
Both  -XX:NewSize and  -XX:MaxNewSize are used, young gen will be between those 2 sizes.  But when heap size change, the young gen size will not change accordingly.
If  -XX:NewRatio is used, the Young Gen size is heap size * newRatio.  NewRatio is ignored if it is used with NewSize and MaxNewSize.

10. Does G1 needs a full gc to unload the classes?

No,  G1 triggers marking cycle and unload gc when the metadat space occupancy is higher than some threshold.  There is a flag -XX:+ClassUnloadingWithConcurrentMarking(default on) to enable this behavior.
Sometimes, people see the marking triggered by Metadata threshold happens slower and slower.  Even trigger a full gc.  You can try to decrease  MaxMetaspaceFreeRatio so that G1 will keep the high water mark for that threshold down to trigger marking cycle more frequently.

11. When classes are unloaded (from openjdk mailing list, Stefan.Kalsson)?

 There are different ways to hold classes alive:
1) You have a live reference to the java.lang.ClassLoader (or subclass) object.
2) You have a live reference to any of the java.lang.Class objects belonging to the ClassLoader.
3) You have an instance of a class, that is described by any of the java.lang.Class objects belonging to the ClassLoader.
4) You have a "dependency" between a class in another ClassLoader, refering to a class in the ClassLoader that is kept alive. E.g. from class resolution in the constant pool, super classes, interfaces, JSR 292 specific code.

You have to break all of these chains before your classes and class loader will be eligible for class unloading.  We only require one marking cycle to clean out metadata. Maybe something is holding references to your class loader, classes, instances, but then gets cleaned out during the second GC. Things to look out for are, for example, SoftReferences and Finalizers.

After the remark phase, after the concurrent marking phase, we have enough information to unload the classes. Most of the JVM internal data structures are cleaned out during the remark phase, the actual metaspace memory is handed back during the cleanup phase.

If the JVM manages to clean out an entire "virtual space area" of metadata, the memory will be hand back to the OS and the amount of committed memory will be decreased. If not, it puts the committed memory onto the free lists so that it can be used by other metaspaces.

No comments:

Post a Comment