< prev index next >
src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp
Print this page
rev 53994 : 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:
@@ -1,7 +1,7 @@
/*
- * 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -24,11 +24,10 @@
#include "precompiled.hpp"
#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"
elapsedTimer AdaptiveSizePolicy::_minor_timer;
elapsedTimer AdaptiveSizePolicy::_major_timer;
@@ -47,20 +46,15 @@
uint gc_cost_ratio) :
_throughput_goal(1.0 - double(1.0 / (1.0 + (double) gc_cost_ratio))),
_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);
_avg_minor_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
_avg_major_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
@@ -275,141 +269,113 @@
set_change_young_gen_for_throughput(0);
set_decrease_for_footprint(0);
set_decide_at_full_gc(0);
}
-void AdaptiveSizePolicy::check_gc_overhead_limit(
- size_t young_live,
- size_t eden_live,
+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,
- bool is_full_gc,
- GCCause::Cause gc_cause,
- SoftRefPolicy* soft_ref_policy) {
+ 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) {}
- // 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
+ 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 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.
+ // 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 the
- // young gen or the average of the live in the young gen.
+ // 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()->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());
+ 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 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());
+ 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)(
- "PSAdaptiveSizePolicy::check_gc_overhead_limit:"
+ "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);
-
- 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();
- }
- }
+ promo_limit, _max_eden_size, total_free_limit,
+ _max_old_gen_size, _max_eden_size,
+ (size_t)mem_free_limit);
- 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());
- }
+ 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 eden_live,
+ size_t max_old_gen_size,
+ size_t max_eden_size,
+ bool is_full_gc,
+ GCCause::Cause gc_cause,
+ SoftRefPolicy* soft_ref_policy) {
+
+ 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
bool AdaptiveSizePolicy::print() const {
assert(UseAdaptiveSizePolicy, "UseAdaptiveSizePolicy need to be enabled.");
< prev index next >