Summary
-------
Introduce the product command line option `GCCardSizeInBytes` to set the range of memory covered by a card.
Problem
-------
In an incremental garbage collector, if you evacuate an object during garbage collection, i.e. move it, any other references to that object must be adjusted to the new object location. It is essential for performance to find these references from non-evacuated areas quickly.
In Serial, Parallel and G1 GC the card table helps finding these references: the elements of this array, the cards, subdivide the Java heap into small (few hundred bytes) disjunct areas that during garbage collection store information whether that small area potentially contains such a reference. Such a card potentially containing a reference is considered "dirty" (as opposed to "clean").
During garbage collection, instead of looking through references of all objects of the heap for references into memory that is evacuated, only look for references in the area represented by dirty cards. Since this area is magnitudes smaller than the entirety of non-evacuated Java heap areas, this mechanism is much faster.
The size of the area a card table entry covers ("card size" in the following) is a trade-off between performance and memory usage - larger cards use less memory for the card table array, but require more work during the garbage collection pause to find the sought after references.
Currently card size is fixed at compile time to 512 bytes. It is unknown how that value has been determined; literature suggests that values down to 128 bytes were in use. For an upper limit, current implementation allows up to 1024 bytes for card size.
Internal tests showed reductions in pause time of up to 30% when using a card size of 256 or 1024 bytes depending on the application.
Solution
--------
Allow the user set the card size at VM startup within 128 and 1024 bytes.
Specification
-------------
--- a/src/hotspot/share/gc/shared/gc_globals.hpp
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -692,9 +692,13 @@
product(uintx, GCDrainStackTargetSize, 64, \
"Number of entries we will try to leave on the stack " \
"during parallel gc") \
- range(0, max_juint)
-
-// end of GC_FLAGS
+ range(0, max_juint) \
+ \
+ product(uint, GCCardSizeInBytes, 512, \
+ "Card table entry size (in bytes) for card based collectors") \
+ range(128, 1024) \
+ constraint(GCCardSizeInBytesConstraintFunc,AtParse)
+ // end of GC_FLAGS