提交 8be7836d 编写于 作者: Y ysr

7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot ||...

7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
上级 adff88a9
...@@ -896,7 +896,7 @@ bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(size_t max_promoti ...@@ -896,7 +896,7 @@ bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(size_t max_promoti
size_t available = max_available(); size_t available = max_available();
size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average(); size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average();
bool res = (available >= av_promo) || (available >= max_promotion_in_bytes); bool res = (available >= av_promo) || (available >= max_promotion_in_bytes);
if (PrintGC && Verbose) { if (Verbose && PrintGCDetails) {
gclog_or_tty->print_cr( gclog_or_tty->print_cr(
"CMS: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT")," "CMS: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT"),"
"max_promo("SIZE_FORMAT")", "max_promo("SIZE_FORMAT")",
...@@ -1562,8 +1562,8 @@ bool CMSCollector::shouldConcurrentCollect() { ...@@ -1562,8 +1562,8 @@ bool CMSCollector::shouldConcurrentCollect() {
GenCollectedHeap* gch = GenCollectedHeap::heap(); GenCollectedHeap* gch = GenCollectedHeap::heap();
assert(gch->collector_policy()->is_two_generation_policy(), assert(gch->collector_policy()->is_two_generation_policy(),
"You may want to check the correctness of the following"); "You may want to check the correctness of the following");
if (gch->incremental_collection_will_fail()) { if (gch->incremental_collection_will_fail(true /* consult_young */)) {
if (PrintGCDetails && Verbose) { if (Verbose && PrintGCDetails) {
gclog_or_tty->print("CMSCollector: collect because incremental collection will fail "); gclog_or_tty->print("CMSCollector: collect because incremental collection will fail ");
} }
return true; return true;
...@@ -1927,7 +1927,7 @@ void CMSCollector::decide_foreground_collection_type( ...@@ -1927,7 +1927,7 @@ void CMSCollector::decide_foreground_collection_type(
"You may want to check the correctness of the following"); "You may want to check the correctness of the following");
// Inform cms gen if this was due to partial collection failing. // Inform cms gen if this was due to partial collection failing.
// The CMS gen may use this fact to determine its expansion policy. // The CMS gen may use this fact to determine its expansion policy.
if (gch->incremental_collection_will_fail()) { if (gch->incremental_collection_will_fail(false /* don't consult_young */)) {
assert(!_cmsGen->incremental_collection_failed(), assert(!_cmsGen->incremental_collection_failed(),
"Should have been noticed, reacted to and cleared"); "Should have been noticed, reacted to and cleared");
_cmsGen->set_incremental_collection_failed(); _cmsGen->set_incremental_collection_failed();
...@@ -1936,7 +1936,7 @@ void CMSCollector::decide_foreground_collection_type( ...@@ -1936,7 +1936,7 @@ void CMSCollector::decide_foreground_collection_type(
UseCMSCompactAtFullCollection && UseCMSCompactAtFullCollection &&
((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction) || ((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction) ||
GCCause::is_user_requested_gc(gch->gc_cause()) || GCCause::is_user_requested_gc(gch->gc_cause()) ||
gch->incremental_collection_will_fail()); gch->incremental_collection_will_fail(true /* consult_young */));
*should_start_over = false; *should_start_over = false;
if (clear_all_soft_refs && !*should_compact) { if (clear_all_soft_refs && !*should_compact) {
// We are about to do a last ditch collection attempt // We are about to do a last ditch collection attempt
......
...@@ -287,7 +287,7 @@ inline bool CMSCollector::should_abort_preclean() const { ...@@ -287,7 +287,7 @@ inline bool CMSCollector::should_abort_preclean() const {
// scavenge is done or foreground GC wants to take over collection // scavenge is done or foreground GC wants to take over collection
return _collectorState == AbortablePreclean && return _collectorState == AbortablePreclean &&
(_abort_preclean || _foregroundGCIsActive || (_abort_preclean || _foregroundGCIsActive ||
GenCollectedHeap::heap()->incremental_collection_will_fail()); GenCollectedHeap::heap()->incremental_collection_will_fail(true /* consult_young */));
} }
inline size_t CMSCollector::get_eden_used() const { inline size_t CMSCollector::get_eden_used() const {
......
...@@ -685,7 +685,7 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size, ...@@ -685,7 +685,7 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
result = expand_heap_and_allocate(size, is_tlab); result = expand_heap_and_allocate(size, is_tlab);
} }
return result; // could be null if we are out of space return result; // could be null if we are out of space
} else if (!gch->incremental_collection_will_fail()) { } else if (!gch->incremental_collection_will_fail(false /* don't consult_young */)) {
// Do an incremental collection. // Do an incremental collection.
gch->do_collection(false /* full */, gch->do_collection(false /* full */,
false /* clear_all_soft_refs */, false /* clear_all_soft_refs */,
...@@ -693,6 +693,9 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size, ...@@ -693,6 +693,9 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
is_tlab /* is_tlab */, is_tlab /* is_tlab */,
number_of_generations() - 1 /* max_level */); number_of_generations() - 1 /* max_level */);
} else { } else {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print(" :: Trying full because partial may fail :: ");
}
// Try a full collection; see delta for bug id 6266275 // Try a full collection; see delta for bug id 6266275
// for the original code and why this has been simplified // for the original code and why this has been simplified
// with from-space allocation criteria modified and // with from-space allocation criteria modified and
......
...@@ -483,13 +483,14 @@ void DefNewGeneration::space_iterate(SpaceClosure* blk, ...@@ -483,13 +483,14 @@ void DefNewGeneration::space_iterate(SpaceClosure* blk,
// so we try to allocate the from-space, too. // so we try to allocate the from-space, too.
HeapWord* DefNewGeneration::allocate_from_space(size_t size) { HeapWord* DefNewGeneration::allocate_from_space(size_t size) {
HeapWord* result = NULL; HeapWord* result = NULL;
if (PrintGC && Verbose) { if (Verbose && PrintGCDetails) {
gclog_or_tty->print("DefNewGeneration::allocate_from_space(%u):" gclog_or_tty->print("DefNewGeneration::allocate_from_space(%u):"
" will_fail: %s" " will_fail: %s"
" heap_lock: %s" " heap_lock: %s"
" free: " SIZE_FORMAT, " free: " SIZE_FORMAT,
size, size,
GenCollectedHeap::heap()->incremental_collection_will_fail() ? "true" : "false", GenCollectedHeap::heap()->incremental_collection_will_fail(false /* don't consult_young */) ?
"true" : "false",
Heap_lock->is_locked() ? "locked" : "unlocked", Heap_lock->is_locked() ? "locked" : "unlocked",
from()->free()); from()->free());
} }
...@@ -534,6 +535,9 @@ void DefNewGeneration::collect(bool full, ...@@ -534,6 +535,9 @@ void DefNewGeneration::collect(bool full,
// from this generation, pass on collection; let the next generation // from this generation, pass on collection; let the next generation
// do it. // do it.
if (!collection_attempt_is_safe()) { if (!collection_attempt_is_safe()) {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print(" :: Collection attempt not safe :: ");
}
gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one
return; return;
} }
...@@ -821,6 +825,9 @@ void DefNewGeneration::reset_scratch() { ...@@ -821,6 +825,9 @@ void DefNewGeneration::reset_scratch() {
bool DefNewGeneration::collection_attempt_is_safe() { bool DefNewGeneration::collection_attempt_is_safe() {
if (!to()->is_empty()) { if (!to()->is_empty()) {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print(" :: to is not empty :: ");
}
return false; return false;
} }
if (_next_gen == NULL) { if (_next_gen == NULL) {
...@@ -843,10 +850,18 @@ void DefNewGeneration::gc_epilogue(bool full) { ...@@ -843,10 +850,18 @@ void DefNewGeneration::gc_epilogue(bool full) {
GenCollectedHeap* gch = GenCollectedHeap::heap(); GenCollectedHeap* gch = GenCollectedHeap::heap();
if (full) { if (full) {
DEBUG_ONLY(seen_incremental_collection_failed = false;) DEBUG_ONLY(seen_incremental_collection_failed = false;)
if (!collection_attempt_is_safe()) { if (!collection_attempt_is_safe() && !_eden_space->is_empty()) {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print("DefNewEpilogue: cause(%s), full, not safe, set_failed, set_alloc_from, clear_seen",
GCCause::to_string(gch->gc_cause()));
}
gch->set_incremental_collection_failed(); // Slight lie: a full gc left us in that state gch->set_incremental_collection_failed(); // Slight lie: a full gc left us in that state
set_should_allocate_from_space(); // we seem to be running out of space set_should_allocate_from_space(); // we seem to be running out of space
} else { } else {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print("DefNewEpilogue: cause(%s), full, safe, clear_failed, clear_alloc_from, clear_seen",
GCCause::to_string(gch->gc_cause()));
}
gch->clear_incremental_collection_failed(); // We just did a full collection gch->clear_incremental_collection_failed(); // We just did a full collection
clear_should_allocate_from_space(); // if set clear_should_allocate_from_space(); // if set
} }
...@@ -860,11 +875,20 @@ void DefNewGeneration::gc_epilogue(bool full) { ...@@ -860,11 +875,20 @@ void DefNewGeneration::gc_epilogue(bool full) {
// a full collection in between. // a full collection in between.
if (!seen_incremental_collection_failed && if (!seen_incremental_collection_failed &&
gch->incremental_collection_failed()) { gch->incremental_collection_failed()) {
if (Verbose && PrintGCDetails) {
gclog_or_tty->print("DefNewEpilogue: cause(%s), not full, not_seen_failed, failed, set_seen_failed",
GCCause::to_string(gch->gc_cause()));
}
seen_incremental_collection_failed = true; seen_incremental_collection_failed = true;
} else if (seen_incremental_collection_failed) { } else if (seen_incremental_collection_failed) {
assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed(), if (Verbose && PrintGCDetails) {
gclog_or_tty->print("DefNewEpilogue: cause(%s), not full, seen_failed, will_clear_seen_failed",
GCCause::to_string(gch->gc_cause()));
}
assert(gch->gc_cause() == GCCause::_scavenge_alot ||
(gch->gc_cause() == GCCause::_java_lang_system_gc && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
!gch->incremental_collection_failed(),
"Twice in a row"); "Twice in a row");
seen_incremental_collection_failed = false; seen_incremental_collection_failed = false;
} }
#endif // ASSERT #endif // ASSERT
......
...@@ -935,7 +935,7 @@ void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) { ...@@ -935,7 +935,7 @@ void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) {
void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs, void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs,
int max_level) { int max_level) {
int local_max_level; int local_max_level;
if (!incremental_collection_will_fail() && if (!incremental_collection_will_fail(false /* don't consult_young */) &&
gc_cause() == GCCause::_gc_locker) { gc_cause() == GCCause::_gc_locker) {
local_max_level = 0; local_max_level = 0;
} else { } else {
...@@ -951,7 +951,7 @@ void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs, ...@@ -951,7 +951,7 @@ void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs,
// A scavenge may not have been attempted, or may have // A scavenge may not have been attempted, or may have
// been attempted and failed, because the old gen was too full // been attempted and failed, because the old gen was too full
if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker && if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker &&
incremental_collection_will_fail()) { incremental_collection_will_fail(false /* don't consult_young */)) {
if (PrintGCDetails) { if (PrintGCDetails) {
gclog_or_tty->print_cr("GC locker: Trying a full collection " gclog_or_tty->print_cr("GC locker: Trying a full collection "
"because scavenge failed"); "because scavenge failed");
......
...@@ -477,13 +477,17 @@ public: ...@@ -477,13 +477,17 @@ public:
bool no_allocs_since_save_marks(int level); bool no_allocs_since_save_marks(int level);
// Returns true if an incremental collection is likely to fail. // Returns true if an incremental collection is likely to fail.
bool incremental_collection_will_fail() { // We optionally consult the young gen, if asked to do so;
// otherwise we base our answer on whether the previous incremental
// collection attempt failed with no corrective action as of yet.
bool incremental_collection_will_fail(bool consult_young) {
// Assumes a 2-generation system; the first disjunct remembers if an // Assumes a 2-generation system; the first disjunct remembers if an
// incremental collection failed, even when we thought (second disjunct) // incremental collection failed, even when we thought (second disjunct)
// that it would not. // that it would not.
assert(heap()->collector_policy()->is_two_generation_policy(), assert(heap()->collector_policy()->is_two_generation_policy(),
"the following definition may not be suitable for an n(>2)-generation system"); "the following definition may not be suitable for an n(>2)-generation system");
return incremental_collection_failed() || !get_gen(0)->collection_attempt_is_safe(); return incremental_collection_failed() ||
(consult_young && !get_gen(0)->collection_attempt_is_safe());
} }
// If a generation bails out of an incremental collection, // If a generation bails out of an incremental collection,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册