Skip to content
Permalink
Browse files
8274191: Improve g1 evacuation failure injector performance
Reviewed-by: kbarrett, ayang
  • Loading branch information
Thomas Schatzl committed Sep 24, 2021
1 parent d91e227 commit db23ecdfae44a5387c2407e9e0f300f08770e7c0
Showing 6 changed files with 25 additions and 21 deletions.
@@ -85,6 +85,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
_num_optional_regions(optional_cset_length),
_numa(g1h->numa()),
_obj_alloc_stat(NULL),
NOT_PRODUCT(_evac_failure_inject_counter(0) COMMA)
_preserved_marks(preserved_marks),
_evacuation_failed_info(),
_evac_failure_regions(evac_failure_regions)
@@ -414,6 +415,12 @@ HeapWord* G1ParScanThreadState::allocate_copy_slow(G1HeapRegionAttr* dest_attr,
return obj_ptr;
}

#ifndef PRODUCT
bool G1ParScanThreadState::inject_evacuation_failure() {
return _g1h->evac_failure_injector()->evacuation_should_fail(_evac_failure_inject_counter);
}
#endif

NOINLINE
void G1ParScanThreadState::undo_allocation(G1HeapRegionAttr dest_attr,
HeapWord* obj_ptr,
@@ -458,7 +465,7 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio
assert(_g1h->is_in_reserved(obj_ptr), "Allocated memory should be in the heap");

// Should this evacuation fail?
if (_g1h->evac_failure_injector()->evacuation_should_fail()) {
if (inject_evacuation_failure()) {
// Doing this after all the allocation attempts also tests the
// undo_allocation() method too.
undo_allocation(dest_attr, obj_ptr, word_sz, node_index);
@@ -515,7 +522,6 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio
G1SkipCardEnqueueSetter x(&_scanner, dest_attr.is_young());
obj->oop_iterate_backwards(&_scanner, klass);
return obj;

} else {
_plab_allocator->undo_allocation(dest_attr, obj_ptr, word_sz, node_index);
return forward_ptr;
@@ -98,10 +98,15 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
size_t* _obj_alloc_stat;

// Per-thread evacuation failure data structures.
#ifndef PRODUCT
size_t _evac_failure_inject_counter;
#endif
PreservedMarks* _preserved_marks;
EvacuationFailedInfo _evacuation_failed_info;
G1EvacFailureRegions* _evac_failure_regions;

bool inject_evacuation_failure() PRODUCT_RETURN_( return false; );

public:
G1ParScanThreadState(G1CollectedHeap* g1h,
G1RedirtyCardsQueueSet* rdcqs,
@@ -72,11 +72,8 @@ void G1YoungGCEvacFailureInjector::arm_if_needed() {
}

void G1YoungGCEvacFailureInjector::reset() {
if (G1EvacuationFailureALot) {
_last_collection_with_evacuation_failure = G1CollectedHeap::heap()->total_collections();
_evacuation_failure_object_count = 0;
_inject_evacuation_failure_for_current_gc = false;
}
_last_collection_with_evacuation_failure = G1CollectedHeap::heap()->total_collections();
_inject_evacuation_failure_for_current_gc = false;
}

#endif // #ifndef PRODUCT
@@ -45,9 +45,6 @@ class G1YoungGCEvacFailureInjector {
// Used to determine whether evacuation failure injection should be in effect
// for the current GC.
size_t _last_collection_with_evacuation_failure;

// The number of evacuations between induced failures.
volatile size_t _evacuation_failure_object_count;
#endif

bool arm_if_needed_for_gc_type(bool for_young_gc,
@@ -59,8 +56,9 @@ class G1YoungGCEvacFailureInjector {
// GC (based upon the type of GC and which command line flags are set);
void arm_if_needed() PRODUCT_RETURN;

// Return true if it's time to cause an evacuation failure.
bool evacuation_should_fail() PRODUCT_RETURN_( return false; );
// Return true if it's time to cause an evacuation failure; the caller
// provides the (preferably thread-local) counter to minimize performance impact.
bool evacuation_should_fail(size_t& counter) PRODUCT_RETURN_( return false; );

// Reset the evacuation failure injection counters. Should be called at
// the end of an evacuation pause in which an evacuation failure occurred.
@@ -25,23 +25,21 @@
#ifndef SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_INLINE_HPP
#define SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_INLINE_HPP

#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"

#include "gc/g1/g1_globals.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"

#ifndef PRODUCT

inline bool G1YoungGCEvacFailureInjector::evacuation_should_fail() {
if (!G1EvacuationFailureALot || !_inject_evacuation_failure_for_current_gc) {
inline bool G1YoungGCEvacFailureInjector::evacuation_should_fail(size_t& counter) {
if (!_inject_evacuation_failure_for_current_gc) {
return false;
}
// Injecting evacuation failures is in effect for current GC
// Access to _evacuation_failure_alot_count is not atomic;
// the value does not have to be exact.
if (++_evacuation_failure_object_count < G1EvacuationFailureALotCount) {
if (++counter < G1EvacuationFailureALotCount) {
return false;
}
_evacuation_failure_object_count = 0;
counter = 0;
return true;
}

@@ -275,7 +275,7 @@
\
develop(uintx, G1EvacuationFailureALotCount, 1000, \
"Number of successful evacuations between evacuation failures " \
"occurring at object copying") \
"occurring at object copying per thread") \
\
develop(uintx, G1EvacuationFailureALotInterval, 5, \
"Total collections between forced triggering of evacuation " \

1 comment on commit db23ecd

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on db23ecd Sep 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.