-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
8278917: Use Prev Bitmap for recording evac failed objects #6867
Conversation
👋 Welcome back sjohanss! A progress list of the required criteria for merging this PR into |
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor comments/suggestions.
|
||
// All objects that failed evacuation has been marked in the prev bitmap. | ||
// Use the bitmap to apply the above closure to all failing objects. | ||
hr->apply_to_marked_objects(const_cast<G1CMBitMap*>(_g1h->concurrent_mark()->prev_mark_bitmap()), &rspc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe placing the bitmap on its own line, sth like bitmap = const_cast<G1CMBitMap*>(_g1h->concurrent_mark()->prev_mark_bitmap())
?
@@ -191,6 +190,7 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure { | |||
hr->rem_set()->clear_locked(true); | |||
|
|||
hr->note_self_forwarding_removal_end(live_bytes); | |||
_g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that you are editing this method, why if (_evac_failure_regions->contains(hr->hrm_index()))
? I thought that's the precondition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not check the call-chain, but I agree this should be an assert. Probably a left-over from the past when all heap regions were iterated.
Will fix.
// The compaction closure not only copies the object to the new | ||
// location, but also clears the bitmap for it. This is needed | ||
// for bitmap verification as well as for being able to use the | ||
// prev_bitmap for evacuation failures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of clearing the bit for each obj individually, I wonder if clearing the bitmap for the whole region will be faster. IOW, just call collector()->mark_bitmap()->clear_region(hr);
unconditionally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this first, just removing the G1VerifyBitmaps
condition. But this will cause a notable regression for regions with very few marked objects. I'm not certain that regression is to bad, but I did not see anything suggesting that clearing the whole bitmap afterwards would be quicker in any other scenario either. So went with the bit-by-bit approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume mem write is more expensive (or at least not more efficient) than mem read, so the performance changes make sense to me.
And a comment about the observation of the regression will be helpful in the future for others who think this might be a optimization point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a few lines about this.
// Young regions should always have cleared bitmaps, so only clear old. | ||
if (hr->is_old()) { | ||
_g1h->clear_region_bitmap(hr); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to assert "Young regions should always have cleared bitmaps"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Certainly! Good idea, will fix.
@kstefanj 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 /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 48 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review Albert.
@@ -191,6 +190,7 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure { | |||
hr->rem_set()->clear_locked(true); | |||
|
|||
hr->note_self_forwarding_removal_end(live_bytes); | |||
_g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not check the call-chain, but I agree this should be an assert. Probably a left-over from the past when all heap regions were iterated.
Will fix.
// The compaction closure not only copies the object to the new | ||
// location, but also clears the bitmap for it. This is needed | ||
// for bitmap verification as well as for being able to use the | ||
// prev_bitmap for evacuation failures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did this first, just removing the G1VerifyBitmaps
condition. But this will cause a notable regression for regions with very few marked objects. I'm not certain that regression is to bad, but I did not see anything suggesting that clearing the whole bitmap afterwards would be quicker in any other scenario either. So went with the bit-by-bit approach.
// Young regions should always have cleared bitmaps, so only clear old. | ||
if (hr->is_old()) { | ||
_g1h->clear_region_bitmap(hr); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Certainly! Good idea, will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm. Just some minor comments.
@@ -2957,14 +2957,18 @@ void G1CollectedHeap::record_obj_copy_mem_stats() { | |||
create_g1_evac_summary(&_old_evac_stats)); | |||
} | |||
|
|||
void G1CollectedHeap::clear_region_bitmap(HeapRegion* hr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe currently a name like clear_region_in_prev_bitmap
is more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -1252,6 +1254,9 @@ class G1CollectedHeap : public CollectedHeap { | |||
inline bool is_obj_dead_full(const oop obj, const HeapRegion* hr) const; | |||
inline bool is_obj_dead_full(const oop obj) const; | |||
|
|||
// Mark the live object that failed evacuation in the correct bitmap(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we are explicitly using prev bitmap, so maybe comment should say so too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, in my first version I also marked in the next bitmap here if needed, but decided to leave it in the failure handling. Will update.
_cm->mark_in_prev_bitmap(obj); | ||
} | ||
|
||
// Zapping clears the bitmap, make sure it didn't clear to much. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/to/too
// The compaction closure not only copies the object to the new | ||
// location, but also clears the bitmap for it. This is needed | ||
// for bitmap verification as well as for being able to use the | ||
// prev_bitmap for evacuation failures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume mem write is more expensive (or at least not more efficient) than mem read, so the performance changes make sense to me.
And a comment about the observation of the regression will be helpful in the future for others who think this might be a optimization point.
@@ -74,6 +80,7 @@ size_t G1FullGCCompactTask::G1CompactRegionClosure::apply(oop obj) { | |||
cast_to_oop(destination)->init_mark(); | |||
assert(cast_to_oop(destination)->klass() != NULL, "should have a class"); | |||
|
|||
clear_bitmap(obj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a simple comment here will be helpful, although we already have comments where G1CompactRegionClosure is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review Hamlin.
@@ -2957,14 +2957,18 @@ void G1CollectedHeap::record_obj_copy_mem_stats() { | |||
create_g1_evac_summary(&_old_evac_stats)); | |||
} | |||
|
|||
void G1CollectedHeap::clear_region_bitmap(HeapRegion* hr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -1252,6 +1254,9 @@ class G1CollectedHeap : public CollectedHeap { | |||
inline bool is_obj_dead_full(const oop obj, const HeapRegion* hr) const; | |||
inline bool is_obj_dead_full(const oop obj) const; | |||
|
|||
// Mark the live object that failed evacuation in the correct bitmap(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, in my first version I also marked in the next bitmap here if needed, but decided to leave it in the failure handling. Will update.
@@ -74,6 +80,7 @@ size_t G1FullGCCompactTask::G1CompactRegionClosure::apply(oop obj) { | |||
cast_to_oop(destination)->init_mark(); | |||
assert(cast_to_oop(destination)->klass() != NULL, "should have a class"); | |||
|
|||
clear_bitmap(obj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
// The compaction closure not only copies the object to the new | ||
// location, but also clears the bitmap for it. This is needed | ||
// for bitmap verification as well as for being able to use the | ||
// prev_bitmap for evacuation failures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a few lines about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm, some bikeshedding :p
// The compaction closure not only copies the object to the new | ||
// location, but also clears the bitmap for it. This is needed | ||
// for bitmap verification as well as for being able to use the | ||
// prev_bitmap for evacuation failures. Testing showed that it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... for evacuation failures in the next young collections.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
@@ -50,7 +50,7 @@ class G1FullGCCompactTask : public G1FullGCTask { | |||
|
|||
class G1CompactRegionClosure : public StackObj { | |||
G1CMBitMap* _bitmap; | |||
|
|||
void clear_bitmap(oop object); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a name like par_clear_in_prev_bitmap
like other single bit operations for the bitmap (drop the par
if you do not like it) - we do not clear the entire bitmap as the current name implies to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll update the name, but will leave the "par"-part out as this is not done with a par-operation. Since the whole region is handled by a single worker the clearing is done with a _bm.clear_bit()
and I can't come up with a case where this would be a problem. The regions and bitmap should be aligned so that there are no words in the bitmap spanning two regions, right?
// of these objs later in *remove self forward* phase of post evacuation. | ||
r->record_evac_failure_obj(old); | ||
|
||
// Objects failing evacuation will turn in to old objects since the regions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/in to/into
r->record_evac_failure_obj(old); | ||
|
||
// Objects failing evacuation will turn in to old objects since the regions | ||
// is relabeled as such. We mark the failing objects in the prev bitmap and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/is/are
src/hotspot/share/gc/g1/g1RemSet.cpp
Outdated
@@ -1259,6 +1259,46 @@ class G1MergeHeapRootsTask : public WorkerTask { | |||
G1MergeCardSetStats stats() const { return _stats; } | |||
}; | |||
|
|||
// Closure to clear the prev bitmap for any old region in the CSet. This is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer if terms like CSet
are not abbreviated in comments, i.e. s/CSet/collection set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree.
src/hotspot/share/gc/g1/g1RemSet.cpp
Outdated
} | ||
}; | ||
|
||
// Helper to allow multiple closure to be applied when |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/multiple/two :)
@@ -622,6 +622,8 @@ class G1CollectedHeap : public CollectedHeap { | |||
// for all regions. | |||
void verify_region_attr_remset_is_tracked() PRODUCT_RETURN; | |||
|
|||
void clear_region_in_prev_bitmap(HeapRegion* hr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A name like clear_prev_bitmap_for_region
would be preferable to me, putting what we clear right next to the verb.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer this as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the bikeshedding 😄
@@ -622,6 +622,8 @@ class G1CollectedHeap : public CollectedHeap { | |||
// for all regions. | |||
void verify_region_attr_remset_is_tracked() PRODUCT_RETURN; | |||
|
|||
void clear_region_in_prev_bitmap(HeapRegion* hr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer this as well.
// The compaction closure not only copies the object to the new | ||
// location, but also clears the bitmap for it. This is needed | ||
// for bitmap verification as well as for being able to use the | ||
// prev_bitmap for evacuation failures. Testing showed that it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
@@ -50,7 +50,7 @@ class G1FullGCCompactTask : public G1FullGCTask { | |||
|
|||
class G1CompactRegionClosure : public StackObj { | |||
G1CMBitMap* _bitmap; | |||
|
|||
void clear_bitmap(oop object); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll update the name, but will leave the "par"-part out as this is not done with a par-operation. Since the whole region is handled by a single worker the clearing is done with a _bm.clear_bit()
and I can't come up with a case where this would be a problem. The regions and bitmap should be aligned so that there are no words in the bitmap spanning two regions, right?
src/hotspot/share/gc/g1/g1RemSet.cpp
Outdated
@@ -1259,6 +1259,46 @@ class G1MergeHeapRootsTask : public WorkerTask { | |||
G1MergeCardSetStats stats() const { return _stats; } | |||
}; | |||
|
|||
// Closure to clear the prev bitmap for any old region in the CSet. This is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still good :)
Thanks Albert, Hamlin and Thomas for your reviews. I will integrate this a little later when some final sanity testing is finished. |
/integrate |
Going to push as commit f4f2f32.
Your commit was automatically rebased without conflicts. |
Please review this enhancement to improve evacuation failure handling in G1.
Summary
Prior to this change the evacuation failure handling recorded the failing objects during evacuation in a set backed by
G1SegmentedArray
. Later when processing the objects the set needed to be sorted to allow for efficient zapping of the areas between the live objects. During this phase we also mark the live objects in the prev mark bitmap to allow for correct verification.This change optimizes away sorting part by directly marking failing objects in the mark bitmap. The marks are then used to determine which objects need to be processed (and what areas should be zapped) when cleaning up after the evacuation phase. For this to work, there can't be any stale marks in the bitmap. This require us to do some additional clearing that was not needed before. Both at the end of a Full GC and during preparation for mixed collections.
This additional clearing does cost a bit, but are done in parallel and the benefit outweighs the cost. For the Full GC the clearing of the bitmap is moved into the compaction closure. This is something that was thought of before and the closure already have the bitmap as a member. This way the Full GC regression becomes minimal.
Testing
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/6867/head:pull/6867
$ git checkout pull/6867
Update a local copy of the PR:
$ git checkout pull/6867
$ git pull https://git.openjdk.java.net/jdk pull/6867/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 6867
View PR using the GUI difftool:
$ git pr show -t 6867
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/6867.diff