8142484: Let IHOP follow the current capacity, not the maximum capacity

Instead of following the current heap capacity, let all IHOP calculations follow the maximum capacity.

Reviewed-by: brutisso, jmasa
This commit is contained in:
Thomas Schatzl 2016-03-07 10:56:06 +01:00
parent 1cd0d034f8
commit 595f1f01e4
3 changed files with 36 additions and 22 deletions

View File

@ -269,6 +269,8 @@ G1CollectorPolicy::G1CollectorPolicy() :
_reserve_regions = 0; _reserve_regions = 0;
_cset_chooser = new CollectionSetChooser(); _cset_chooser = new CollectionSetChooser();
_ihop_control = create_ihop_control();
} }
G1CollectorPolicy::~G1CollectorPolicy() { G1CollectorPolicy::~G1CollectorPolicy() {
@ -469,8 +471,6 @@ void G1CollectorPolicy::post_heap_initialize() {
if (max_young_size != MaxNewSize) { if (max_young_size != MaxNewSize) {
FLAG_SET_ERGO(size_t, MaxNewSize, max_young_size); FLAG_SET_ERGO(size_t, MaxNewSize, max_young_size);
} }
_ihop_control = create_ihop_control();
} }
void G1CollectorPolicy::initialize_flags() { void G1CollectorPolicy::initialize_flags() {
@ -565,6 +565,8 @@ void G1CollectorPolicy::record_new_heap_size(uint new_number_of_regions) {
_reserve_regions = (uint) ceil(reserve_regions_d); _reserve_regions = (uint) ceil(reserve_regions_d);
_young_gen_sizer->heap_size_changed(new_number_of_regions); _young_gen_sizer->heap_size_changed(new_number_of_regions);
_ihop_control->update_target_occupancy(new_number_of_regions * HeapRegion::GrainBytes);
} }
uint G1CollectorPolicy::calculate_young_list_desired_min_length( uint G1CollectorPolicy::calculate_young_list_desired_min_length(
@ -1234,13 +1236,11 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t
G1IHOPControl* G1CollectorPolicy::create_ihop_control() const { G1IHOPControl* G1CollectorPolicy::create_ihop_control() const {
if (G1UseAdaptiveIHOP) { if (G1UseAdaptiveIHOP) {
return new G1AdaptiveIHOPControl(InitiatingHeapOccupancyPercent, return new G1AdaptiveIHOPControl(InitiatingHeapOccupancyPercent,
G1CollectedHeap::heap()->max_capacity(),
&_predictor, &_predictor,
G1ReservePercent, G1ReservePercent,
G1HeapWastePercent); G1HeapWastePercent);
} else { } else {
return new G1StaticIHOPControl(InitiatingHeapOccupancyPercent, return new G1StaticIHOPControl(InitiatingHeapOccupancyPercent);
G1CollectedHeap::heap()->max_capacity());
} }
} }

View File

@ -29,15 +29,21 @@
#include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTrace.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
G1IHOPControl::G1IHOPControl(double initial_ihop_percent, size_t target_occupancy) : G1IHOPControl::G1IHOPControl(double initial_ihop_percent) :
_initial_ihop_percent(initial_ihop_percent), _initial_ihop_percent(initial_ihop_percent),
_target_occupancy(target_occupancy), _target_occupancy(0),
_last_allocated_bytes(0), _last_allocated_bytes(0),
_last_allocation_time_s(0.0) _last_allocation_time_s(0.0)
{ {
assert(_initial_ihop_percent >= 0.0 && _initial_ihop_percent <= 100.0, "Initial IHOP value must be between 0 and 100 but is %.3f", initial_ihop_percent); assert(_initial_ihop_percent >= 0.0 && _initial_ihop_percent <= 100.0, "Initial IHOP value must be between 0 and 100 but is %.3f", initial_ihop_percent);
} }
void G1IHOPControl::update_target_occupancy(size_t new_target_occupancy) {
log_debug(gc, ihop)("Target occupancy update: old: " SIZE_FORMAT "B, new: " SIZE_FORMAT "B",
_target_occupancy, new_target_occupancy);
_target_occupancy = new_target_occupancy;
}
void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t allocated_bytes, size_t additional_buffer_size) { void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t allocated_bytes, size_t additional_buffer_size) {
assert(allocation_time_s >= 0.0, "Allocation time must be positive but is %.3f", allocation_time_s); assert(allocation_time_s >= 0.0, "Allocation time must be positive but is %.3f", allocation_time_s);
@ -46,6 +52,7 @@ void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t allo
} }
void G1IHOPControl::print() { void G1IHOPControl::print() {
assert(_target_occupancy > 0, "Target occupancy still not updated yet.");
size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold(); size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold();
log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B, " log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B, "
"recent allocation size: " SIZE_FORMAT "B, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms", "recent allocation size: " SIZE_FORMAT "B, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms",
@ -60,6 +67,7 @@ void G1IHOPControl::print() {
} }
void G1IHOPControl::send_trace_event(G1NewTracer* tracer) { void G1IHOPControl::send_trace_event(G1NewTracer* tracer) {
assert(_target_occupancy > 0, "Target occupancy still not updated yet.");
tracer->report_basic_ihop_statistics(get_conc_mark_start_threshold(), tracer->report_basic_ihop_statistics(get_conc_mark_start_threshold(),
_target_occupancy, _target_occupancy,
G1CollectedHeap::heap()->used(), G1CollectedHeap::heap()->used(),
@ -68,10 +76,9 @@ void G1IHOPControl::send_trace_event(G1NewTracer* tracer) {
last_marking_length_s()); last_marking_length_s());
} }
G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent, size_t target_occupancy) : G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent) :
G1IHOPControl(ihop_percent, target_occupancy), G1IHOPControl(ihop_percent),
_last_marking_length_s(0.0) { _last_marking_length_s(0.0) {
assert(_target_occupancy > 0, "Target occupancy must be larger than zero.");
} }
#ifndef PRODUCT #ifndef PRODUCT
@ -85,7 +92,8 @@ static void test_update(G1IHOPControl* ctrl, double alloc_time, size_t alloc_amo
void G1StaticIHOPControl::test() { void G1StaticIHOPControl::test() {
size_t const initial_ihop = 45; size_t const initial_ihop = 45;
G1StaticIHOPControl ctrl(initial_ihop, 100); G1StaticIHOPControl ctrl(initial_ihop);
ctrl.update_target_occupancy(100);
size_t threshold = ctrl.get_conc_mark_start_threshold(); size_t threshold = ctrl.get_conc_mark_start_threshold();
assert(threshold == initial_ihop, assert(threshold == initial_ihop,
@ -115,11 +123,10 @@ void G1StaticIHOPControl::test() {
#endif #endif
G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent, G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent,
size_t initial_target_occupancy,
G1Predictions const* predictor, G1Predictions const* predictor,
size_t heap_reserve_percent, size_t heap_reserve_percent,
size_t heap_waste_percent) : size_t heap_waste_percent) :
G1IHOPControl(ihop_percent, initial_target_occupancy), G1IHOPControl(ihop_percent),
_predictor(predictor), _predictor(predictor),
_marking_times_s(10, 0.95), _marking_times_s(10, 0.95),
_allocation_rate_s(10, 0.95), _allocation_rate_s(10, 0.95),
@ -130,6 +137,7 @@ G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent,
} }
size_t G1AdaptiveIHOPControl::actual_target_threshold() const { size_t G1AdaptiveIHOPControl::actual_target_threshold() const {
guarantee(_target_occupancy > 0, "Target occupancy still not updated yet.");
// The actual target threshold takes the heap reserve and the expected waste in // The actual target threshold takes the heap reserve and the expected waste in
// free space into account. // free space into account.
// _heap_reserve is that part of the total heap capacity that is reserved for // _heap_reserve is that part of the total heap capacity that is reserved for
@ -227,7 +235,8 @@ void G1AdaptiveIHOPControl::test() {
// target_size - (young_size + alloc_amount/alloc_time * marking_time) // target_size - (young_size + alloc_amount/alloc_time * marking_time)
G1Predictions pred(0.95); G1Predictions pred(0.95);
G1AdaptiveIHOPControl ctrl(initial_threshold, target_size, &pred, 0, 0); G1AdaptiveIHOPControl ctrl(initial_threshold, &pred, 0, 0);
ctrl.update_target_occupancy(target_size);
// First "load". // First "load".
size_t const alloc_time1 = 2; size_t const alloc_time1 = 2;
@ -288,5 +297,6 @@ void G1AdaptiveIHOPControl::test() {
void IHOP_test() { void IHOP_test() {
G1StaticIHOPControl::test(); G1StaticIHOPControl::test();
G1AdaptiveIHOPControl::test();
} }
#endif #endif

View File

@ -38,7 +38,8 @@ class G1IHOPControl : public CHeapObj<mtGC> {
protected: protected:
// The initial IHOP value relative to the target occupancy. // The initial IHOP value relative to the target occupancy.
double _initial_ihop_percent; double _initial_ihop_percent;
// The target maximum occupancy of the heap. // The target maximum occupancy of the heap. The target occupancy is the number
// of bytes when marking should be finished and reclaim started.
size_t _target_occupancy; size_t _target_occupancy;
// Most recent complete mutator allocation period in seconds. // Most recent complete mutator allocation period in seconds.
@ -46,10 +47,9 @@ class G1IHOPControl : public CHeapObj<mtGC> {
// Amount of bytes allocated during _last_allocation_time_s. // Amount of bytes allocated during _last_allocation_time_s.
size_t _last_allocated_bytes; size_t _last_allocated_bytes;
// Initialize an instance with the initial IHOP value in percent and the target // Initialize an instance with the initial IHOP value in percent. The target
// occupancy. The target occupancy is the number of bytes when marking should // occupancy will be updated at the first heap expansion.
// be finished and reclaim started. G1IHOPControl(double initial_ihop_percent);
G1IHOPControl(double initial_ihop_percent, size_t target_occupancy);
// Most recent time from the end of the initial mark to the start of the first // Most recent time from the end of the initial mark to the start of the first
// mixed gc. // mixed gc.
@ -60,6 +60,8 @@ class G1IHOPControl : public CHeapObj<mtGC> {
// Get the current non-young occupancy at which concurrent marking should start. // Get the current non-young occupancy at which concurrent marking should start.
virtual size_t get_conc_mark_start_threshold() = 0; virtual size_t get_conc_mark_start_threshold() = 0;
// Adjust target occupancy.
virtual void update_target_occupancy(size_t new_target_occupancy);
// Update information about time during which allocations in the Java heap occurred, // Update information about time during which allocations in the Java heap occurred,
// how large these allocations were in bytes, and an additional buffer. // how large these allocations were in bytes, and an additional buffer.
// The allocations should contain any amount of space made unusable for further // The allocations should contain any amount of space made unusable for further
@ -86,9 +88,12 @@ class G1StaticIHOPControl : public G1IHOPControl {
protected: protected:
double last_marking_length_s() const { return _last_marking_length_s; } double last_marking_length_s() const { return _last_marking_length_s; }
public: public:
G1StaticIHOPControl(double ihop_percent, size_t target_occupancy); G1StaticIHOPControl(double ihop_percent);
size_t get_conc_mark_start_threshold() { return (size_t) (_initial_ihop_percent * _target_occupancy / 100.0); } size_t get_conc_mark_start_threshold() {
guarantee(_target_occupancy > 0, "Target occupancy must have been initialized.");
return (size_t) (_initial_ihop_percent * _target_occupancy / 100.0);
}
virtual void update_marking_length(double marking_length_s) { virtual void update_marking_length(double marking_length_s) {
assert(marking_length_s > 0.0, "Marking length must be larger than zero but is %.3f", marking_length_s); assert(marking_length_s > 0.0, "Marking length must be larger than zero but is %.3f", marking_length_s);
@ -132,7 +137,6 @@ class G1AdaptiveIHOPControl : public G1IHOPControl {
virtual double last_marking_length_s() const { return _marking_times_s.last(); } virtual double last_marking_length_s() const { return _marking_times_s.last(); }
public: public:
G1AdaptiveIHOPControl(double ihop_percent, G1AdaptiveIHOPControl(double ihop_percent,
size_t initial_target_occupancy,
G1Predictions const* predictor, G1Predictions const* predictor,
size_t heap_reserve_percent, // The percentage of total heap capacity that should not be tapped into. size_t heap_reserve_percent, // The percentage of total heap capacity that should not be tapped into.
size_t heap_waste_percent); // The percentage of the free space in the heap that we think is not usable for allocation. size_t heap_waste_percent); // The percentage of the free space in the heap that we think is not usable for allocation.