8390907: Genshen: Improve mark loop performance - #32488
Conversation
|
👋 Welcome back wkemper! A progress list of the required criteria for merging this PR into |
|
@earthling-amzn This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 7 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
|
@earthling-amzn The following labels will be automatically applied to this pull request:
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. |
|
The total number of required reviews for this PR has been set to 2 based on the presence of this label: |
| // may visit class metadata that lives outside the heap so we cannot | ||
| // assume (or assert) that `p` is in old. | ||
| heap->old_generation()->mark_card_as_dirty(p); | ||
| } else if (GENERATION == GLOBAL && heap->has_affiliation(p, OLD_GENERATION) && heap->has_affiliation(obj, YOUNG_GENERATION)) { |
There was a problem hiding this comment.
Should this be also predicated with DIRTY, or am I missing something?
There was a problem hiding this comment.
REDIRTY is specifically for the remembered set scan. I have added more asserts to make this more clear. I also though about calling this parameter REREMEMBER, but it looked too weird.
| inline bool is_write_card_dirty(HeapWord* p) const; | ||
| inline void mark_card_as_dirty(HeapWord* p); | ||
|
|
||
| void mark_card_as_dirty(HeapWord* p) const { |
There was a problem hiding this comment.
Functions like these really belong in .inline.hpp. Putting anything non-trivial in the .hpp risks circular dependencies that are hard to untangle.
|
|
||
| public: | ||
| template<class T, ShenandoahGenerationType GENERATION> | ||
| template<class T, ShenandoahGenerationType GENERATION, bool REDIRTY = false> |
There was a problem hiding this comment.
We usually do not do default values for template parameters to force callers to decide whether they want it or not. Are there many instances that would require fixing if you drop = false?
There was a problem hiding this comment.
Only one caller would set it true. The instantiations aren't spread all over the code base or anything, I was just trying to minimize changes in the PR.
|
@earthling-amzn this pull request can not be integrated into git checkout simplify-reremember-during-mark
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
|
In my runs, I also see |
| void ShenandoahDirectCardMarkRememberedSet::mark_card_as_dirty(HeapWord* p) const { | ||
| size_t index = card_index_for_addr(p); | ||
| CardValue* bp = &(_card_table->write_byte_map())[index]; | ||
| bp[0] = CardTable::dirty_card_val(); |
There was a problem hiding this comment.
Another question: does this write need to be conditional? We default to +UseCondCardMark to avoid contention on marks that are already dirty. Is the path we are optimizing benefits from the same optimization?
There was a problem hiding this comment.
For a young GC, the read card table will have been cleaned and then swapped with the write table, so the write table is clean here (which is why the rset closure redirties the cards at it scans the read table). During a global GC in generational mode, the rset is not scanned, but the tables are still swapped, so cards should also be clean here.
This function is also called during operations on the discovered list for reference processing, but I expect the write volume would not be high there as the card is only marked when an old reference is linked to a young reference.
kdnilsen
left a comment
There was a problem hiding this comment.
Thanks. Nice performance improvements.
| * Copyright (c) 2015, 2020, Red Hat, Inc. All rights reserved. | ||
| * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
| * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. | ||
| * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. |
There was a problem hiding this comment.
This moves dates backwards, so it does not look right.
| if (ShenandoahHeapRegion::is_in_same_region(maybe_old, maybe_young)) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Just for my understanding. This is a narrower check than we can do? I would have tried to check that region affiliations are different. But that performs access to affiliation bitmap, so that's why we do this address-only check, right?
There are several small changes here that add up to a 10% to 12% reduction in mark times on specjbb2015.
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/32488/head:pull/32488$ git checkout pull/32488Update a local copy of the PR:
$ git checkout pull/32488$ git pull https://git.openjdk.org/jdk.git pull/32488/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 32488View PR using the GUI difftool:
$ git pr show -t 32488Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/32488.diff
Using Webrev
Link to Webrev Comment