Skip to content

8361252: Compact Full-GC Forwarding #26133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

rkennke
Copy link
Contributor

@rkennke rkennke commented Jul 4, 2025

I'd like to propose a new Full-GC forwarding scheme for the Serial, Parallel, G1 and Shenandoah GCs.

Primarily, it solves a limitation when compact object headers are turned on: the above mentioned GCs can then not handle heaps > 8TB, and we turn off compact object headers, instead. I realize that this is most likely not an issue in practice for Serial GC (who would want this?). It may be an issue with Parallel and G1 GCs (I know some folks run with Parallel GC on large batch jobs, where latency is not a concern at all. G1 may be useful in the same situation, perhaps). It is an issue with Shenandoah GC, because large heaps is one reason why Shenandoah exists to begin with. (ZGC doesn't have this problem, because it does not have a full-GC.) Given that I think we should make compact object headers on by default in JDK 26, and obsolete the old mode in JDK 27, I think it'd be useful to have the new implementation available now.

Second, it's a first step and preparation towards 4-byte-headers, which I hope to bring into JDK 27. With 4-byte-headers, we only have 9 bits in the header for storing forwarding-pointers during full-GC, and this implementation provides that with minimal overhead.

I've proposed something similar before (see #20605), but this improved implementation is simpler, uses less memory overhead, and has basically no performance impact.

There is a large comment at the top of fullGCForwarding.hpp which explains the algorithm in detail. I am not repeating it here. I'll just state some basic properties:

  • The algorithm exploits the fact that full-GC forwarding happens (mostly) sequentially (within a region/block).
  • It divides the heap into blocks. Given N header bits for addressing, the size of each block is 2^N heap-words. In this change, we have 40 bits - the other bits are two 'lock-bits' to indicate forwarding and 22 compressed-class-bits that we need to protect (that is the point of this patch). This means a block-size of 8TB. (With 4-byte-headers, we will only have 9 bits, therefore the block-size is 2KB).
  • For each such block, we need one word in a forwarding-table to store the base-pointer for that block. The size of that table is 1/(2^N)th of the heap-size in words. In the current proposed change, that 'table' is just a single word for each 8TB. With 4-byte-headers, the table will be 1/512th of the heap size.
  • If necessary (e.g. when the sequential-property is broken, such as on space boundaries, in G1's serial compaction, and when forwarding to the very last word of a block), then we use a fallback-concurrent-hashtable. This happens very rarely and doesn't really affect performance.
  • Speaking of performance: in my measurements I could not see any regressions, performance looks neutral.

In order to facilitate testing and later reduction of the implementation to fewer bits, I template-ized the forwarding table implementation on the number of bits. This allows me to write unit tests that don't take >8TB of heap and stress some of the interesting scenarios, without affecting performance in normal HotSpot product situations.

Testing:

  • In Lilliput 2 (fewer-bits version)
  • tier1-4
  • hotspot_gc

Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8361252: Compact Full-GC Forwarding (Enhancement - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/26133/head:pull/26133
$ git checkout pull/26133

Update a local copy of the PR:
$ git checkout pull/26133
$ git pull https://git.openjdk.org/jdk.git pull/26133/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 26133

View PR using the GUI difftool:
$ git pr show -t 26133

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/26133.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 4, 2025

👋 Welcome back rkennke! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Jul 4, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk
Copy link

openjdk bot commented Jul 4, 2025

@rkennke The following labels will be automatically applied to this pull request:

  • hotspot
  • shenandoah

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added hotspot hotspot-dev@openjdk.org shenandoah shenandoah-dev@openjdk.org labels Jul 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hotspot hotspot-dev@openjdk.org shenandoah shenandoah-dev@openjdk.org
Development

Successfully merging this pull request may close these issues.

1 participant