--- old/src/share/vm/gc/g1/g1CollectorPolicy.cpp 2015-11-19 11:52:57.435832421 +0100 +++ new/src/share/vm/gc/g1/g1CollectorPolicy.cpp 2015-11-19 11:52:57.348829865 +0100 @@ -1209,21 +1209,9 @@ size_t last_unrestrained_young_length = update_young_list_max_and_target_length(); update_rs_lengths_prediction(); - // Only update IHOP information on regular GCs. - if (update_stats) { - double marking_to_mixed_time = -1.0; - if (!collector_state()->last_gc_was_young() && _initial_mark_to_mixed.has_result()) { - marking_to_mixed_time = _initial_mark_to_mixed.last_marking_time(); - assert(marking_to_mixed_time > 0.0, - "Initial mark to mixed time must be larger than zero but is %.3f", - marking_to_mixed_time); - } - - update_ihop_statistics(marking_to_mixed_time, - app_time_ms / 1000.0, - _last_old_allocated_bytes, - last_unrestrained_young_length * HeapRegion::GrainBytes); - } + update_ihop_prediction(app_time_ms / 1000.0, + _last_old_allocated_bytes, + last_unrestrained_young_length * HeapRegion::GrainBytes); _last_old_allocated_bytes = 0; // Note that _mmu_tracker->max_gc_time() returns the time in seconds. @@ -1256,19 +1244,28 @@ G1CollectedHeap::heap()->max_capacity()); } -void G1CollectorPolicy::update_ihop_statistics(double marking_time, - double mutator_time_s, +void G1CollectorPolicy::update_ihop_prediction(double mutator_time_s, size_t mutator_alloc_bytes, size_t young_gen_size) { - bool report = false; + // Always try to update IHOP prediction. Even evacuation failures give information + // about e.g. whether to start IHOP earlier next time. - // To avoid using really small times that may be caused by e.g. back-to-back gcs - // we filter them out. + // Avoid using really small application times that might create samples with + // very high or very low values. They may be caused by e.g. back-to-back gcs. double const min_valid_time = 1e-6; - if (marking_time > min_valid_time) { - _ihop_control->update_marking_length(marking_time); - report = true; + bool report = false; + + double marking_to_mixed_time = -1.0; + if (!collector_state()->last_gc_was_young() && _initial_mark_to_mixed.has_result()) { + marking_to_mixed_time = _initial_mark_to_mixed.last_marking_time(); + assert(marking_to_mixed_time > 0.0, + "Initial mark to mixed time must be larger than zero but is %.3f", + marking_to_mixed_time); + if (marking_to_mixed_time > min_valid_time) { + _ihop_control->update_marking_length(marking_to_mixed_time); + report = true; + } } // As an approximation for the young gc promotion rates during marking we use --- old/src/share/vm/gc/g1/g1CollectorPolicy.hpp 2015-11-19 11:52:57.937847169 +0100 +++ new/src/share/vm/gc/g1/g1CollectorPolicy.hpp 2015-11-19 11:52:57.851844642 +0100 @@ -169,8 +169,8 @@ G1IHOPControl* _ihop_control; G1IHOPControl* create_ihop_control() const; - void update_ihop_statistics(double marking_to_mixed_time, - double mutator_time_s, + // Update the IHOP control with necessary statistics. + void update_ihop_prediction(double mutator_time_s, size_t mutator_alloc_bytes, size_t young_gen_size); void report_ihop_statistics(); --- old/src/share/vm/gc/g1/g1IHOPControl.cpp 2015-11-19 11:52:58.421861388 +0100 +++ new/src/share/vm/gc/g1/g1IHOPControl.cpp 2015-11-19 11:52:58.334858832 +0100 @@ -29,19 +29,22 @@ G1IHOPControl::G1IHOPControl(double initial_ihop_percent, size_t target_occupancy) : _initial_ihop_percent(initial_ihop_percent), - _target_occupancy(target_occupancy) { + _target_occupancy(target_occupancy), + _last_allocated_bytes(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); } -G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent, size_t target_occupancy) : - G1IHOPControl(ihop_percent, target_occupancy), - _last_allocation_time_s(0.0), - _last_allocated_bytes(0), - _last_marking_length_s(0.0) { - assert(_target_occupancy > 0, "Target occupancy must be larger than zero."); +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); + + _last_allocation_time_s = allocation_time_s; + _last_allocated_bytes = allocated_bytes; } -void G1StaticIHOPControl::print() { +void G1IHOPControl::print() { + size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold(); ergo_verbose6(ErgoIHOP, "basic information", ergo_format_reason("value update") @@ -49,13 +52,19 @@ ergo_format_byte("target occupancy") ergo_format_byte("current occupancy") ergo_format_double("recent old gen allocation rate") - ergo_format_ms("recent marking phase length"), - get_conc_mark_start_threshold(), - _initial_ihop_percent, + ergo_format_double("recent marking phase length"), + cur_conc_mark_start_threshold, + cur_conc_mark_start_threshold * 100.0 / _target_occupancy, _target_occupancy, G1CollectedHeap::heap()->used(), _last_allocation_time_s > 0.0 ? _last_allocated_bytes / _last_allocation_time_s : 0.0, - _last_marking_length_s * 1000.0); + last_marking_length_s()); +} + +G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent, size_t target_occupancy) : + G1IHOPControl(ihop_percent, target_occupancy), + _last_marking_length_s(0.0) { + assert(_target_occupancy > 0, "Target occupancy must be larger than zero."); } #ifndef PRODUCT --- old/src/share/vm/gc/g1/g1IHOPControl.hpp 2015-11-19 11:52:58.979877782 +0100 +++ new/src/share/vm/gc/g1/g1IHOPControl.hpp 2015-11-19 11:52:58.889875138 +0100 @@ -37,10 +37,19 @@ // The target maximum occupancy of the heap. size_t _target_occupancy; + // Most recent complete mutator allocation period in seconds. + double _last_allocation_time_s; + // Amount of bytes allocated during _last_allocation_time_s. + size_t _last_allocated_bytes; + // Initialize an instance with the initial IHOP value in percent and the target // occupancy. The target occupancy is the number of bytes when marking should // be finished and reclaim started. 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 + // mixed gc. + virtual double last_marking_length_s() const = 0; public: virtual ~G1IHOPControl() { } @@ -55,41 +64,32 @@ // Together with the target occupancy, this additional buffer should contain the // difference between old gen size and total heap size at the start of reclamation, // and space required for that reclamation. - virtual void update_allocation_info(double allocation_time_s, size_t allocated_bytes, size_t additional_buffer_size) = 0; + virtual void update_allocation_info(double allocation_time_s, size_t allocated_bytes, size_t additional_buffer_size); // Update the time spent in the mutator beginning from the end of initial mark to // the first mixed gc. virtual void update_marking_length(double marking_length_s) = 0; - virtual void print() = 0; + virtual void print(); }; // The returned concurrent mark starting occupancy threshold is a fixed value // relative to the maximum heap size. class G1StaticIHOPControl : public G1IHOPControl { - // Most recent complete mutator allocation period in seconds. - double _last_allocation_time_s; - // Amount of bytes allocated during _last_allocation_time_s. - size_t _last_allocated_bytes; // Most recent mutator time between the end of initial mark to the start of the // first mixed gc. double _last_marking_length_s; + protected: + double last_marking_length_s() const { return _last_marking_length_s; } public: G1StaticIHOPControl(double ihop_percent, size_t target_occupancy); size_t get_conc_mark_start_threshold() { return (size_t) (_initial_ihop_percent * _target_occupancy / 100.0); } - virtual void 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); - _last_allocation_time_s = allocation_time_s; - _last_allocated_bytes = allocated_bytes; - } - 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); _last_marking_length_s = marking_length_s; } - virtual void print(); #ifndef PRODUCT static void test(); #endif