8212206: Refactor AdaptiveSizePolicy to separate out code related to GC overhead
Summary: Move check_gc_overhead_limit() and related code to its own class
Reviewed-by: tschatzl, pliden, jiangli
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -1498,8 +1498,7 @@
// Has the GC time limit been exceeded?
size_t max_eden_size = _young_gen->max_eden_size();
GCCause::Cause gc_cause = heap->gc_cause();
- size_policy()->check_gc_overhead_limit(_young_gen->used(),
- _young_gen->eden()->used(),
+ size_policy()->check_gc_overhead_limit(_young_gen->eden()->used(),
_cmsGen->max_capacity(),
max_eden_size,
full,
--- a/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.cpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -118,11 +118,6 @@
_avg_base_footprint = PerfDataManager::create_variable(SUN_GC, cname,
PerfData::U_Bytes, (jlong) ps_size_policy()->avg_base_footprint()->average(), CHECK);
- cname = PerfDataManager::counter_name(name_space(), "gcTimeLimitExceeded");
- _gc_overhead_limit_exceeded_counter =
- PerfDataManager::create_variable(SUN_GC, cname,
- PerfData::U_Events, ps_size_policy()->gc_overhead_limit_exceeded(), CHECK);
-
cname = PerfDataManager::counter_name(name_space(), "liveAtLastFullGc");
_live_at_last_full_gc_counter =
PerfDataManager::create_variable(SUN_GC, cname,
--- a/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp Tue Jan 15 15:59:47 2019 -0800
@@ -51,7 +51,6 @@
PerfVariable* _live_space;
PerfVariable* _free_space;
PerfVariable* _avg_base_footprint;
- PerfVariable* _gc_overhead_limit_exceeded_counter;
PerfVariable* _live_at_last_full_gc_counter;
PerfVariable* _old_capacity;
PerfVariable* _boundary_moved;
@@ -177,7 +176,7 @@
);
}
inline void update_gc_overhead_limit_exceeded_counter() {
- _gc_overhead_limit_exceeded_counter->set_value(
+ gc_overhead_limit_exceeded_counter()->set_value(
(jlong) ps_size_policy()->gc_overhead_limit_exceeded());
}
inline void update_live_at_last_full_gc_counter() {
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -316,8 +316,7 @@
max_eden_size,
true /* full gc*/);
- size_policy->check_gc_overhead_limit(young_live,
- eden_live,
+ size_policy->check_gc_overhead_limit(eden_live,
max_old_gen_size,
max_eden_size,
true /* full gc*/,
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -1889,8 +1889,7 @@
max_eden_size,
true /* full gc*/);
- size_policy->check_gc_overhead_limit(young_live,
- eden_live,
+ size_policy->check_gc_overhead_limit(eden_live,
max_old_gen_size,
max_eden_size,
true /* full gc*/,
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -537,8 +537,7 @@
max_eden_size,
false /* not full gc*/);
- size_policy->check_gc_overhead_limit(young_live,
- eden_live,
+ size_policy->check_gc_overhead_limit(eden_live,
max_old_gen_size,
max_eden_size,
false /* not full gc*/,
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
#include "gc/shared/adaptiveSizePolicy.hpp"
#include "gc/shared/gcCause.hpp"
#include "gc/shared/gcUtil.inline.hpp"
-#include "gc/shared/softRefPolicy.hpp"
#include "logging/log.hpp"
#include "runtime/timer.hpp"
@@ -49,16 +48,11 @@
_eden_size(init_eden_size),
_promo_size(init_promo_size),
_survivor_size(init_survivor_size),
- _gc_overhead_limit_exceeded(false),
- _print_gc_overhead_limit_would_be_exceeded(false),
- _gc_overhead_limit_count(0),
_latest_minor_mutator_interval_seconds(0),
_threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0),
_gc_pause_goal_sec(gc_pause_goal_sec),
_young_gen_change_for_minor_throughput(0),
_old_gen_change_for_major_throughput(0) {
- assert(AdaptiveSizePolicyGCTimeLimitThreshold > 0,
- "No opportunity to clear SoftReferences before GC overhead limit");
_avg_minor_pause =
new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
_avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
@@ -277,8 +271,90 @@
set_decide_at_full_gc(0);
}
+class AdaptiveSizePolicyTimeOverheadTester: public GCOverheadTester {
+ double _gc_cost;
+
+ public:
+ AdaptiveSizePolicyTimeOverheadTester(double gc_cost) : _gc_cost(gc_cost) {}
+
+ bool is_exceeded() {
+ return _gc_cost > (GCTimeLimit / 100.0);
+ }
+};
+
+class AdaptiveSizePolicySpaceOverheadTester: public GCOverheadTester {
+ size_t _eden_live;
+ size_t _max_old_gen_size;
+ size_t _max_eden_size;
+ size_t _promo_size;
+ double _avg_eden_live;
+ double _avg_old_live;
+
+ public:
+ AdaptiveSizePolicySpaceOverheadTester(size_t eden_live,
+ size_t max_old_gen_size,
+ size_t max_eden_size,
+ size_t promo_size,
+ double avg_eden_live,
+ double avg_old_live) :
+ _eden_live(eden_live),
+ _max_old_gen_size(max_old_gen_size),
+ _max_eden_size(max_eden_size),
+ _promo_size(promo_size),
+ _avg_eden_live(avg_eden_live),
+ _avg_old_live(avg_old_live) {}
+
+ bool is_exceeded() {
+ // _max_eden_size is the upper limit on the size of eden based on
+ // the maximum size of the young generation and the sizes
+ // of the survivor space.
+ // The question being asked is whether the space being recovered by
+ // a collection is low.
+ // free_in_eden is the free space in eden after a collection and
+ // free_in_old_gen is the free space in the old generation after
+ // a collection.
+ //
+ // Use the minimum of the current value of the live in eden
+ // or the average of the live in eden.
+ // If the current value drops quickly, that should be taken
+ // into account (i.e., don't trigger if the amount of free
+ // space has suddenly jumped up). If the current is much
+ // higher than the average, use the average since it represents
+ // the longer term behavior.
+ const size_t live_in_eden =
+ MIN2(_eden_live, (size_t)_avg_eden_live);
+ const size_t free_in_eden = _max_eden_size > live_in_eden ?
+ _max_eden_size - live_in_eden : 0;
+ const size_t free_in_old_gen = (size_t)(_max_old_gen_size - _avg_old_live);
+ const size_t total_free_limit = free_in_old_gen + free_in_eden;
+ const size_t total_mem = _max_old_gen_size + _max_eden_size;
+ const double free_limit_ratio = GCHeapFreeLimit / 100.0;
+ const double mem_free_limit = total_mem * free_limit_ratio;
+ const double mem_free_old_limit = _max_old_gen_size * free_limit_ratio;
+ const double mem_free_eden_limit = _max_eden_size * free_limit_ratio;
+ size_t promo_limit = (size_t)(_max_old_gen_size - _avg_old_live);
+ // But don't force a promo size below the current promo size. Otherwise,
+ // the promo size will shrink for no good reason.
+ promo_limit = MAX2(promo_limit, _promo_size);
+
+ log_trace(gc, ergo)(
+ "AdaptiveSizePolicySpaceOverheadTester::is_exceeded:"
+ " promo_limit: " SIZE_FORMAT
+ " max_eden_size: " SIZE_FORMAT
+ " total_free_limit: " SIZE_FORMAT
+ " max_old_gen_size: " SIZE_FORMAT
+ " max_eden_size: " SIZE_FORMAT
+ " mem_free_limit: " SIZE_FORMAT,
+ promo_limit, _max_eden_size, total_free_limit,
+ _max_old_gen_size, _max_eden_size,
+ (size_t)mem_free_limit);
+
+ return free_in_old_gen < (size_t)mem_free_old_limit &&
+ free_in_eden < (size_t)mem_free_eden_limit;
+ }
+};
+
void AdaptiveSizePolicy::check_gc_overhead_limit(
- size_t young_live,
size_t eden_live,
size_t max_old_gen_size,
size_t max_eden_size,
@@ -286,128 +362,18 @@
GCCause::Cause gc_cause,
SoftRefPolicy* soft_ref_policy) {
- // Ignore explicit GC's. Exiting here does not set the flag and
- // does not reset the count. Updating of the averages for system
- // GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC.
- if (GCCause::is_user_requested_gc(gc_cause) ||
- GCCause::is_serviceability_requested_gc(gc_cause)) {
- return;
- }
- // eden_limit is the upper limit on the size of eden based on
- // the maximum size of the young generation and the sizes
- // of the survivor space.
- // The question being asked is whether the gc costs are high
- // and the space being recovered by a collection is low.
- // free_in_young_gen is the free space in the young generation
- // after a collection and promo_live is the free space in the old
- // generation after a collection.
- //
- // Use the minimum of the current value of the live in the
- // young gen or the average of the live in the young gen.
- // If the current value drops quickly, that should be taken
- // into account (i.e., don't trigger if the amount of free
- // space has suddenly jumped up). If the current is much
- // higher than the average, use the average since it represents
- // the longer term behavior.
- const size_t live_in_eden =
- MIN2(eden_live, (size_t) avg_eden_live()->average());
- const size_t free_in_eden = max_eden_size > live_in_eden ?
- max_eden_size - live_in_eden : 0;
- const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());
- const size_t total_free_limit = free_in_old_gen + free_in_eden;
- const size_t total_mem = max_old_gen_size + max_eden_size;
- const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0);
- const double mem_free_old_limit = max_old_gen_size * (GCHeapFreeLimit/100.0);
- const double mem_free_eden_limit = max_eden_size * (GCHeapFreeLimit/100.0);
- const double gc_cost_limit = GCTimeLimit/100.0;
- size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average());
- // But don't force a promo size below the current promo size. Otherwise,
- // the promo size will shrink for no good reason.
- promo_limit = MAX2(promo_limit, _promo_size);
-
-
- log_trace(gc, ergo)(
- "PSAdaptiveSizePolicy::check_gc_overhead_limit:"
- " promo_limit: " SIZE_FORMAT
- " max_eden_size: " SIZE_FORMAT
- " total_free_limit: " SIZE_FORMAT
- " max_old_gen_size: " SIZE_FORMAT
- " max_eden_size: " SIZE_FORMAT
- " mem_free_limit: " SIZE_FORMAT,
- promo_limit, max_eden_size, total_free_limit,
- max_old_gen_size, max_eden_size,
- (size_t) mem_free_limit);
-
- bool print_gc_overhead_limit_would_be_exceeded = false;
- if (is_full_gc) {
- if (gc_cost() > gc_cost_limit &&
- free_in_old_gen < (size_t) mem_free_old_limit &&
- free_in_eden < (size_t) mem_free_eden_limit) {
- // Collections, on average, are taking too much time, and
- // gc_cost() > gc_cost_limit
- // we have too little space available after a full gc.
- // total_free_limit < mem_free_limit
- // where
- // total_free_limit is the free space available in
- // both generations
- // total_mem is the total space available for allocation
- // in both generations (survivor spaces are not included
- // just as they are not included in eden_limit).
- // mem_free_limit is a fraction of total_mem judged to be an
- // acceptable amount that is still unused.
- // The heap can ask for the value of this variable when deciding
- // whether to thrown an OutOfMemory error.
- // Note that the gc time limit test only works for the collections
- // of the young gen + tenured gen and not for collections of the
- // permanent gen. That is because the calculation of the space
- // freed by the collection is the free space in the young gen +
- // tenured gen.
- // At this point the GC overhead limit is being exceeded.
- inc_gc_overhead_limit_count();
- if (UseGCOverheadLimit) {
- if (gc_overhead_limit_count() >=
- AdaptiveSizePolicyGCTimeLimitThreshold){
- // All conditions have been met for throwing an out-of-memory
- set_gc_overhead_limit_exceeded(true);
- // Avoid consecutive OOM due to the gc time limit by resetting
- // the counter.
- reset_gc_overhead_limit_count();
- } else {
- // The required consecutive collections which exceed the
- // GC time limit may or may not have been reached. We
- // are approaching that condition and so as not to
- // throw an out-of-memory before all SoftRef's have been
- // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
- // The clearing will be done on the next GC.
- bool near_limit = gc_overhead_limit_near();
- if (near_limit) {
- soft_ref_policy->set_should_clear_all_soft_refs(true);
- log_trace(gc, ergo)("Nearing GC overhead limit, will be clearing all SoftReference");
- }
- }
- }
- // Set this even when the overhead limit will not
- // cause an out-of-memory. Diagnostic message indicating
- // that the overhead limit is being exceeded is sometimes
- // printed.
- print_gc_overhead_limit_would_be_exceeded = true;
-
- } else {
- // Did not exceed overhead limits
- reset_gc_overhead_limit_count();
- }
- }
-
- if (UseGCOverheadLimit) {
- if (gc_overhead_limit_exceeded()) {
- log_trace(gc, ergo)("GC is exceeding overhead limit of " UINTX_FORMAT "%%", GCTimeLimit);
- reset_gc_overhead_limit_count();
- } else if (print_gc_overhead_limit_would_be_exceeded) {
- assert(gc_overhead_limit_count() > 0, "Should not be printing");
- log_trace(gc, ergo)("GC would exceed overhead limit of " UINTX_FORMAT "%% %d consecutive time(s)",
- GCTimeLimit, gc_overhead_limit_count());
- }
- }
+ AdaptiveSizePolicyTimeOverheadTester time_overhead(gc_cost());
+ AdaptiveSizePolicySpaceOverheadTester space_overhead(eden_live,
+ max_old_gen_size,
+ max_eden_size,
+ _promo_size,
+ avg_eden_live()->average(),
+ avg_old_live()->average());
+ _overhead_checker.check_gc_overhead_limit(&time_overhead,
+ &space_overhead,
+ is_full_gc,
+ gc_cause,
+ soft_ref_policy);
}
// Printing
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp Tue Jan 15 15:59:47 2019 -0800
@@ -26,6 +26,7 @@
#define SHARE_GC_SHARED_ADAPTIVESIZEPOLICY_HPP
#include "gc/shared/gcCause.hpp"
+#include "gc/shared/gcOverheadChecker.hpp"
#include "gc/shared/gcUtil.hpp"
#include "memory/allocation.hpp"
@@ -34,7 +35,6 @@
// Forward decls
class elapsedTimer;
-class SoftRefPolicy;
class AdaptiveSizePolicy : public CHeapObj<mtGC> {
friend class GCAdaptivePolicyCounters;
@@ -81,18 +81,8 @@
size_t _survivor_size; // calculated survivor size in bytes
- // This is a hint for the heap: we've detected that GC times
- // are taking longer than GCTimeLimit allows.
- bool _gc_overhead_limit_exceeded;
- // Use for diagnostics only. If UseGCOverheadLimit is false,
- // this variable is still set.
- bool _print_gc_overhead_limit_would_be_exceeded;
- // Count of consecutive GC that have exceeded the
- // GC time limit criterion
- uint _gc_overhead_limit_count;
- // This flag signals that GCTimeLimit is being exceeded
- // but may not have done so for the required number of consecutive
- // collections
+ // Support for UseGCOverheadLimit
+ GCOverheadChecker _overhead_checker;
// Minor collection timers used to determine both
// pause and interval times for collections
@@ -412,26 +402,20 @@
return _survivor_size;
}
- // This is a hint for the heap: we've detected that gc times
- // are taking longer than GCTimeLimit allows.
- // Most heaps will choose to throw an OutOfMemoryError when
- // this occurs but it is up to the heap to request this information
- // of the policy
bool gc_overhead_limit_exceeded() {
- return _gc_overhead_limit_exceeded;
+ return _overhead_checker.gc_overhead_limit_exceeded();
}
void set_gc_overhead_limit_exceeded(bool v) {
- _gc_overhead_limit_exceeded = v;
+ _overhead_checker.set_gc_overhead_limit_exceeded(v);
}
- // Tests conditions indicate the GC overhead limit is being approached.
bool gc_overhead_limit_near() {
- return gc_overhead_limit_count() >=
- (AdaptiveSizePolicyGCTimeLimitThreshold - 1);
+ return _overhead_checker.gc_overhead_limit_near();
}
- uint gc_overhead_limit_count() { return _gc_overhead_limit_count; }
- void reset_gc_overhead_limit_count() { _gc_overhead_limit_count = 0; }
- void inc_gc_overhead_limit_count() { _gc_overhead_limit_count++; }
+
+ void reset_gc_overhead_limit_count() {
+ _overhead_checker.reset_gc_overhead_limit_count();
+ }
// accessors for flags recording the decisions to resize the
// generations to meet the pause goal.
@@ -448,8 +432,7 @@
// Check the conditions for an out-of-memory due to excessive GC time.
// Set _gc_overhead_limit_exceeded if all the conditions have been met.
- void check_gc_overhead_limit(size_t young_live,
- size_t eden_live,
+ void check_gc_overhead_limit(size_t eden_live,
size_t max_old_gen_size,
size_t max_eden_size,
bool is_full_gc,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcOverheadChecker.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/gcOverheadChecker.hpp"
+#include "gc/shared/softRefPolicy.hpp"
+#include "logging/log.hpp"
+
+GCOverheadChecker::GCOverheadChecker() :
+ _gc_overhead_limit_exceeded(false),
+ _print_gc_overhead_limit_would_be_exceeded(false),
+ _gc_overhead_limit_count(0) {
+ assert(GCOverheadLimitThreshold > 0,
+ "No opportunity to clear SoftReferences before GC overhead limit");
+}
+
+void GCOverheadChecker::check_gc_overhead_limit(GCOverheadTester* time_overhead,
+ GCOverheadTester* space_overhead,
+ bool is_full_gc,
+ GCCause::Cause gc_cause,
+ SoftRefPolicy* soft_ref_policy) {
+
+ // Ignore explicit GC's. Exiting here does not set the flag and
+ // does not reset the count.
+ if (GCCause::is_user_requested_gc(gc_cause) ||
+ GCCause::is_serviceability_requested_gc(gc_cause)) {
+ return;
+ }
+
+ bool print_gc_overhead_limit_would_be_exceeded = false;
+ if (is_full_gc) {
+ if (time_overhead->is_exceeded() && space_overhead->is_exceeded()) {
+ // Collections, on average, are taking too much time, and
+ // we have too little space available after a full gc.
+ // At this point the GC overhead limit is being exceeded.
+ _gc_overhead_limit_count++;
+ if (UseGCOverheadLimit) {
+ if (_gc_overhead_limit_count >= GCOverheadLimitThreshold){
+ // All conditions have been met for throwing an out-of-memory
+ set_gc_overhead_limit_exceeded(true);
+ // Avoid consecutive OOM due to the gc time limit by resetting
+ // the counter.
+ reset_gc_overhead_limit_count();
+ } else {
+ // The required consecutive collections which exceed the
+ // GC time limit may or may not have been reached. We
+ // are approaching that condition and so as not to
+ // throw an out-of-memory before all SoftRef's have been
+ // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
+ // The clearing will be done on the next GC.
+ bool near_limit = gc_overhead_limit_near();
+ if (near_limit) {
+ soft_ref_policy->set_should_clear_all_soft_refs(true);
+ log_trace(gc, ergo)("Nearing GC overhead limit, will be clearing all SoftReference");
+ }
+ }
+ }
+ // Set this even when the overhead limit will not
+ // cause an out-of-memory. Diagnostic message indicating
+ // that the overhead limit is being exceeded is sometimes
+ // printed.
+ print_gc_overhead_limit_would_be_exceeded = true;
+
+ } else {
+ // Did not exceed overhead limits
+ reset_gc_overhead_limit_count();
+ }
+ }
+
+ if (UseGCOverheadLimit) {
+ if (gc_overhead_limit_exceeded()) {
+ log_trace(gc, ergo)("GC is exceeding overhead limit of " UINTX_FORMAT "%%", GCTimeLimit);
+ reset_gc_overhead_limit_count();
+ } else if (print_gc_overhead_limit_would_be_exceeded) {
+ assert(_gc_overhead_limit_count > 0, "Should not be printing");
+ log_trace(gc, ergo)("GC would exceed overhead limit of " UINTX_FORMAT "%% %d consecutive time(s)",
+ GCTimeLimit, _gc_overhead_limit_count);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcOverheadChecker.hpp Tue Jan 15 15:59:47 2019 -0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP
+#define SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP
+
+#include "memory/allocation.hpp"
+#include "gc/shared/gcCause.hpp"
+
+class SoftRefPolicy;
+
+class GCOverheadTester: public StackObj {
+public:
+ virtual bool is_exceeded() = 0;
+};
+
+class GCOverheadChecker: public CHeapObj<mtGC> {
+ // This is a hint for the heap: we've detected that GC times
+ // are taking longer than GCTimeLimit allows.
+ bool _gc_overhead_limit_exceeded;
+ // Use for diagnostics only. If UseGCOverheadLimit is false,
+ // this variable is still set.
+ bool _print_gc_overhead_limit_would_be_exceeded;
+ // Count of consecutive GC that have exceeded the
+ // GC time limit criterion
+ uint _gc_overhead_limit_count;
+ // This flag signals that GCTimeLimit is being exceeded
+ // but may not have done so for the required number of consecutive
+ // collections
+
+public:
+ GCOverheadChecker();
+
+ // This is a hint for the heap: we've detected that gc times
+ // are taking longer than GCTimeLimit allows.
+ // Most heaps will choose to throw an OutOfMemoryError when
+ // this occurs but it is up to the heap to request this information
+ // of the policy
+ bool gc_overhead_limit_exceeded() {
+ return _gc_overhead_limit_exceeded;
+ }
+ void set_gc_overhead_limit_exceeded(bool v) {
+ _gc_overhead_limit_exceeded = v;
+ }
+
+ // Tests conditions indicate the GC overhead limit is being approached.
+ bool gc_overhead_limit_near() {
+ return _gc_overhead_limit_count >= (GCOverheadLimitThreshold - 1);
+ }
+ void reset_gc_overhead_limit_count() {
+ _gc_overhead_limit_count = 0;
+ }
+
+ // Check the conditions for an out-of-memory due to excessive GC time.
+ // Set _gc_overhead_limit_exceeded if all the conditions have been met.
+ void check_gc_overhead_limit(GCOverheadTester* time_overhead,
+ GCOverheadTester* space_overhead,
+ bool is_full_gc,
+ GCCause::Cause gc_cause,
+ SoftRefPolicy* soft_ref_policy);
+};
+
+#endif // SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP
--- a/src/hotspot/share/gc/shared/gcPolicyCounters.cpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcPolicyCounters.cpp Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,5 +59,10 @@
_desired_survivor_size =
PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
CHECK);
+
+ cname = PerfDataManager::counter_name(_name_space, "gcTimeLimitExceeded");
+ _gc_overhead_limit_exceeded_counter =
+ PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Events,
+ CHECK);
}
}
--- a/src/hotspot/share/gc/shared/gcPolicyCounters.hpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcPolicyCounters.hpp Tue Jan 15 15:59:47 2019 -0800
@@ -41,6 +41,7 @@
PerfVariable* _tenuring_threshold;
PerfVariable* _desired_survivor_size;
+ PerfVariable* _gc_overhead_limit_exceeded_counter;
const char* _name_space;
@@ -62,6 +63,10 @@
return _desired_survivor_size;
}
+ inline PerfVariable* gc_overhead_limit_exceeded_counter() const {
+ return _gc_overhead_limit_exceeded_counter;
+ }
+
const char* name_space() const { return _name_space; }
virtual void update_counters() {}
--- a/src/hotspot/share/gc/shared/gc_globals.hpp Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -616,7 +616,7 @@
"OutOfMemoryError is thrown (used with GCTimeLimit)") \
range(0, 100) \
\
- develop(uintx, AdaptiveSizePolicyGCTimeLimitThreshold, 5, \
+ develop(uintx, GCOverheadLimitThreshold, 5, \
"Number of consecutive collections before gc time limit fires") \
range(1, max_uintx) \
\