[G1] Why is max. region size restricted to 32m?
Thomas Schatzl
thomas.schatzl at oracle.com
Mon Aug 31 11:50:18 UTC 2020
Hi,
On 25.08.20 07:46, Vishal Chand wrote:
> Hi,
>
> While running G1 with 128g heap, I am observing # of regions close to 4k,
> which is twice the target number of regions G1 tries to achieve (2048). I
> would like to know any major reason/challenges for keeping the max region
> size restricted to 32m, apart from what is mentioned in* src
> <http://ssdbang9:8080/source/xref/jdk14/jdk14/src/>/hotspot
> <http://ssdbang9:8080/source/xref/jdk14/jdk14/src/hotspot/>/share
> <http://ssdbang9:8080/source/xref/jdk14/jdk14/src/hotspot/share/>/gc
> <http://ssdbang9:8080/source/xref/jdk14/jdk14/src/hotspot/share/gc/>/g1
> <http://ssdbang9:8080/source/xref/jdk14/jdk14/src/hotspot/share/gc/g1/>/heapRegionBounds.hpp.
> *
the main reason is that 32m regions have been found a good tradeoff
between region size and space usage in the remembered sets.
G1 stores the locations where references to other regions are as card
indices relative to the start of a region. With a card size of 512 bytes
(the currently compiled-in default), in a 32m region there are exactly
2^16 such cards, which means that g1 can store such an index as 16 bit
integer instead of something larger, saving (lots of) space.
Saving space not only saves that space for other purposes, but most of
the time you're waiting on loading memory into registers/caches during
gc pause.
There are several options here to work around this off the top of my
head, no guarantees that these changes will not trip up somewhere else:
1) use a larger data type for card indices, i.e. change the line
typedef uint16_t card_elem_t;
in sparsePRT.hpp to something larger, i.e. uint32_t ;)
2) use a larger card size, for every doubling here you can double the
region size.
See CardTable::card_shift and related. Particularly with larger heaps a
larger card size might even be advantageous for several reasons.
1024 bytes per card seems certainly okay with nowadays' heap sizes,
maybe even 2048 is still good.
2a) decouple "remembered set cards" from "card table cards" - afaik
for historical reasons they have been set to the same value which
resulted in this problem in the first place.
Note that while 1) is fairly quick to do, it will make the memory
consumption not only of the sparse remembered set representation larger
(effectively doubling it) which may be sort-of-okay'ish (these are like
~100 entries for every region having references into the remembered set
owner's region), but also the fine remembered set representation will
double (e.g. from 8k/per fine remembered set table to 16k/per fine
remembered set table when going from 32 to 64m regions).
That one will hurt *a lot*.
Unless you want to overhaul remembered set data structures completely
(there is some long-ongoing internal effort - always something else
getting in the way), my personal opinion to get the most impact with
"least" effort with the current data structures seems to be 2a above.
I.e. as soon as you untangled card table cards and remembered set cards
usage, you can then scale region size quite some ways without affecting
lots of other things. Option 2 would be interesting and likely much less
effort to get only 64m regions cheaply. (Not sure that 2k+ card table
size is still "good" for 128m+ regions, but without measurements...)
Thanks,
Thomas
More information about the hotspot-gc-dev
mailing list