diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.cpp b/src/hotspot/share/gc/g1/g1IHOPControl.cpp index 34c8cd0366b..43698e9f12b 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.cpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.cpp @@ -28,14 +28,63 @@ #include "gc/g1/g1Trace.hpp" #include "logging/log.hpp" -G1IHOPControl::G1IHOPControl(double initial_ihop_percent, - G1OldGenAllocationTracker const* old_gen_alloc_tracker) : - _initial_ihop_percent(initial_ihop_percent), - _target_occupancy(0), - _last_allocation_time_s(0.0), - _old_gen_alloc_tracker(old_gen_alloc_tracker) -{ - 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); +double G1IHOPControl::predict(const TruncatedSeq* seq) const { + assert(_is_adaptive, "precondition"); + assert(_predictor != nullptr, "precondition"); + + return _predictor->predict_zero_bounded(seq); +} + +bool G1IHOPControl::have_enough_data_for_prediction() const { + assert(_is_adaptive, "precondition"); + + return ((size_t)_marking_times_s.num() >= G1AdaptiveIHOPNumInitialSamples) && + ((size_t)_allocation_rate_s.num() >= G1AdaptiveIHOPNumInitialSamples); +} + +double G1IHOPControl::last_marking_length_s() const { + return _marking_times_s.last(); +} + +size_t G1IHOPControl::actual_target_threshold() const { + assert(_is_adaptive, "precondition"); + + // The actual target threshold takes the heap reserve and the expected waste in + // free space into account. + // _heap_reserve is that part of the total heap capacity that is reserved for + // eventual promotion failure. + // _heap_waste is the amount of space will never be reclaimed in any + // heap, so can not be used for allocation during marking and must always be + // considered. + double safe_total_heap_percentage = + MIN2((double)(_heap_reserve_percent + _heap_waste_percent), 100.0); + + return (size_t)MIN2( + G1CollectedHeap::heap()->max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, + _target_occupancy * (100.0 - _heap_waste_percent) / 100.0 + ); +} + +G1IHOPControl::G1IHOPControl(double ihop_percent, + const G1OldGenAllocationTracker* old_gen_alloc_tracker, + bool adaptive, + const G1Predictions* predictor, + size_t heap_reserve_percent, + size_t heap_waste_percent) + : _is_adaptive(adaptive), + _initial_ihop_percent(ihop_percent), + _target_occupancy(0), + _heap_reserve_percent(heap_reserve_percent), + _heap_waste_percent(heap_waste_percent), + _last_allocation_time_s(0.0), + _old_gen_alloc_tracker(old_gen_alloc_tracker), + _predictor(predictor), + _marking_times_s(10, 0.05), + _allocation_rate_s(10, 0.05), + _last_unrestrained_young_size(0) { + assert(_initial_ihop_percent >= 0.0 && _initial_ihop_percent <= 100.0, + "IHOP percent out of range: %.3f", ihop_percent); + assert(!_is_adaptive || _predictor != nullptr, "precondition"); } void G1IHOPControl::update_target_occupancy(size_t new_target_occupancy) { @@ -50,9 +99,34 @@ void G1IHOPControl::report_statistics(G1NewTracer* new_tracer, size_t non_young_ } void G1IHOPControl::update_allocation_info(double allocation_time_s, 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, "Invalid allocation time: %.3f", allocation_time_s); _last_allocation_time_s = allocation_time_s; + double alloc_rate = _old_gen_alloc_tracker->last_period_old_gen_growth() / allocation_time_s; + _allocation_rate_s.add(alloc_rate); + _last_unrestrained_young_size = additional_buffer_size; +} + +void G1IHOPControl::update_marking_length(double marking_length_s) { + assert(marking_length_s >= 0.0, "Invalid marking length: %.3f", marking_length_s); + _marking_times_s.add(marking_length_s); +} + +size_t G1IHOPControl::get_conc_mark_start_threshold() { + guarantee(_target_occupancy > 0, "Target occupancy must be initialized"); + + if (!_is_adaptive || !have_enough_data_for_prediction()) { + return (size_t)(_initial_ihop_percent * _target_occupancy / 100.0); + } + + double pred_marking_time = predict(&_marking_times_s); + double pred_rate = predict(&_allocation_rate_s); + size_t pred_bytes = (size_t)(pred_marking_time * pred_rate); + size_t predicted_needed = pred_bytes + _last_unrestrained_young_size; + size_t internal_threshold = actual_target_threshold(); + + return predicted_needed < internal_threshold + ? internal_threshold - predicted_needed + : 0; } void G1IHOPControl::print_log(size_t non_young_occupancy) { @@ -68,6 +142,23 @@ void G1IHOPControl::print_log(size_t non_young_occupancy) { _last_allocation_time_s * 1000.0, _last_allocation_time_s > 0.0 ? _old_gen_alloc_tracker->last_period_old_gen_bytes() / _last_allocation_time_s : 0.0, last_marking_length_s() * 1000.0); + + if (!_is_adaptive) { + return; + } + + size_t actual_threshold = actual_target_threshold(); + log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: %zuB (%1.2f), internal target threshold: %zuB, " + "non-young occupancy: %zuB, additional buffer size: %zuB, predicted old gen allocation rate: %1.2fB/s, " + "predicted marking phase length: %1.2fms, prediction active: %s", + cur_conc_mark_start_threshold, + percent_of(cur_conc_mark_start_threshold, actual_threshold), + actual_threshold, + non_young_occupancy, + _last_unrestrained_young_size, + predict(&_allocation_rate_s), + predict(&_marking_times_s) * 1000.0, + have_enough_data_for_prediction() ? "true" : "false"); } void G1IHOPControl::send_trace_event(G1NewTracer* tracer, size_t non_young_occupancy) { @@ -78,121 +169,14 @@ void G1IHOPControl::send_trace_event(G1NewTracer* tracer, size_t non_young_occup _old_gen_alloc_tracker->last_period_old_gen_bytes(), _last_allocation_time_s, last_marking_length_s()); -} -G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent, - G1OldGenAllocationTracker const* old_gen_alloc_tracker) : - G1IHOPControl(ihop_percent, old_gen_alloc_tracker), - _last_marking_length_s(0.0) { -} - -G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent, - G1OldGenAllocationTracker const* old_gen_alloc_tracker, - G1Predictions const* predictor, - size_t heap_reserve_percent, - size_t heap_waste_percent) : - G1IHOPControl(ihop_percent, old_gen_alloc_tracker), - _heap_reserve_percent(heap_reserve_percent), - _heap_waste_percent(heap_waste_percent), - _predictor(predictor), - _marking_times_s(10, 0.05), - _allocation_rate_s(10, 0.05), - _last_unrestrained_young_size(0) -{ -} - -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 - // free space into account. - // _heap_reserve is that part of the total heap capacity that is reserved for - // eventual promotion failure. - // _heap_waste is the amount of space will never be reclaimed in any - // heap, so can not be used for allocation during marking and must always be - // considered. - - double safe_total_heap_percentage = MIN2((double)(_heap_reserve_percent + _heap_waste_percent), 100.0); - - return (size_t)MIN2( - G1CollectedHeap::heap()->max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, - _target_occupancy * (100.0 - _heap_waste_percent) / 100.0 - ); -} - -double G1AdaptiveIHOPControl::predict(TruncatedSeq const* seq) const { - return _predictor->predict_zero_bounded(seq); -} - -bool G1AdaptiveIHOPControl::have_enough_data_for_prediction() const { - return ((size_t)_marking_times_s.num() >= G1AdaptiveIHOPNumInitialSamples) && - ((size_t)_allocation_rate_s.num() >= G1AdaptiveIHOPNumInitialSamples); -} - -size_t G1AdaptiveIHOPControl::get_conc_mark_start_threshold() { - if (have_enough_data_for_prediction()) { - double pred_marking_time = predict(&_marking_times_s); - double pred_promotion_rate = predict(&_allocation_rate_s); - size_t pred_promotion_size = (size_t)(pred_marking_time * pred_promotion_rate); - - size_t predicted_needed_bytes_during_marking = - pred_promotion_size + - // In reality we would need the maximum size of the young gen during - // marking. This is a conservative estimate. - _last_unrestrained_young_size; - - size_t internal_threshold = actual_target_threshold(); - size_t predicted_initiating_threshold = predicted_needed_bytes_during_marking < internal_threshold ? - internal_threshold - predicted_needed_bytes_during_marking : - 0; - return predicted_initiating_threshold; - } else { - // Use the initial value. - return (size_t)(_initial_ihop_percent * _target_occupancy / 100.0); + if (_is_adaptive) { + tracer->report_adaptive_ihop_statistics(get_conc_mark_start_threshold(), + actual_target_threshold(), + non_young_occupancy, + _last_unrestrained_young_size, + predict(&_allocation_rate_s), + predict(&_marking_times_s), + have_enough_data_for_prediction()); } } - -double G1AdaptiveIHOPControl::last_mutator_period_old_allocation_rate() const { - assert(_last_allocation_time_s > 0, "This should not be called when the last GC is full"); - - return _old_gen_alloc_tracker->last_period_old_gen_growth() / _last_allocation_time_s; -} - -void G1AdaptiveIHOPControl::update_allocation_info(double allocation_time_s, - size_t additional_buffer_size) { - G1IHOPControl::update_allocation_info(allocation_time_s, additional_buffer_size); - _allocation_rate_s.add(last_mutator_period_old_allocation_rate()); - - _last_unrestrained_young_size = additional_buffer_size; -} - -void G1AdaptiveIHOPControl::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); - _marking_times_s.add(marking_length_s); -} - -void G1AdaptiveIHOPControl::print_log(size_t non_young_occupancy) { - G1IHOPControl::print_log(non_young_occupancy); - size_t actual_threshold = actual_target_threshold(); - log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: %zuB (%1.2f), internal target threshold: %zuB, " - "non-young occupancy: %zuB, additional buffer size: %zuB, predicted old gen allocation rate: %1.2fB/s, " - "predicted marking phase length: %1.2fms, prediction active: %s", - get_conc_mark_start_threshold(), - percent_of(get_conc_mark_start_threshold(), actual_threshold), - actual_threshold, - non_young_occupancy, - _last_unrestrained_young_size, - predict(&_allocation_rate_s), - predict(&_marking_times_s) * 1000.0, - have_enough_data_for_prediction() ? "true" : "false"); -} - -void G1AdaptiveIHOPControl::send_trace_event(G1NewTracer* tracer, size_t non_young_occupancy) { - G1IHOPControl::send_trace_event(tracer, non_young_occupancy); - tracer->report_adaptive_ihop_statistics(get_conc_mark_start_threshold(), - actual_target_threshold(), - non_young_occupancy, - _last_unrestrained_young_size, - predict(&_allocation_rate_s), - predict(&_marking_times_s), - have_enough_data_for_prediction()); -} diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.hpp b/src/hotspot/share/gc/g1/g1IHOPControl.hpp index 392a12a785a..b6e80d9b422 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.hpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.hpp @@ -32,89 +32,32 @@ class G1Predictions; class G1NewTracer; -// Base class for algorithms that calculate the heap occupancy at which -// concurrent marking should start. This heap usage threshold should be relative -// to old gen size. +// Implements two strategies for calculating the concurrent mark starting occupancy threshold: +// - Static mode: Uses a fixed percentage of the target heap occupancy. +// - Adaptive mode: Predicts a threshold based on allocation rates and marking durations +// to ensure the target occupancy is never exceeded during marking. class G1IHOPControl : public CHeapObj { - protected: + private: + const bool _is_adaptive; + // The initial IHOP value relative to the target occupancy. double _initial_ihop_percent; + // 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; + // Percentage of maximum heap capacity we should avoid to touch + const size_t _heap_reserve_percent; + + // Percentage of free heap that should be considered as waste. + const size_t _heap_waste_percent; + // Most recent complete mutator allocation period in seconds. double _last_allocation_time_s; - const G1OldGenAllocationTracker* _old_gen_alloc_tracker; - // Initialize an instance with the old gen allocation tracker and the - // initial IHOP value in percent. The target occupancy will be updated - // at the first heap expansion. - G1IHOPControl(double ihop_percent, G1OldGenAllocationTracker const* old_gen_alloc_tracker); - - // Most recent time from the end of the concurrent start to the start of the first - // mixed gc. - virtual double last_marking_length_s() const = 0; - - virtual void print_log(size_t non_young_occupancy); - virtual void send_trace_event(G1NewTracer* tracer, size_t non_young_occupancy); - -public: - virtual ~G1IHOPControl() { } - - // Get the current non-young occupancy at which concurrent marking should start. - 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, - // how large these allocations were in bytes, and an additional buffer. - // The allocations should contain any amount of space made unusable for further - // allocation, e.g. any waste caused by TLAB allocation, space at the end of - // humongous objects that can not be used for allocation, etc. - // 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 additional_buffer_size); - // Update the time spent in the mutator beginning from the end of concurrent start to - // the first mixed gc. - virtual void update_marking_length(double marking_length_s) = 0; - - void report_statistics(G1NewTracer* tracer, size_t non_young_occupancy); -}; - -// The returned concurrent mark starting occupancy threshold is a fixed value -// relative to the maximum heap size. -class G1StaticIHOPControl : public G1IHOPControl { - // Most recent mutator time between the end of concurrent 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, G1OldGenAllocationTracker const* old_gen_alloc_tracker); - - 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) { - 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; - } -}; - -// This algorithm tries to return a concurrent mark starting occupancy value that -// makes sure that during marking the given target occupancy is never exceeded, -// based on predictions of current allocation rate and time periods between -// concurrent start and the first mixed gc. -class G1AdaptiveIHOPControl : public G1IHOPControl { - size_t _heap_reserve_percent; // Percentage of maximum heap capacity we should avoid to touch - size_t _heap_waste_percent; // Percentage of free heap that should be considered as waste. - - const G1Predictions * _predictor; + const G1Predictions* _predictor; TruncatedSeq _marking_times_s; TruncatedSeq _allocation_rate_s; @@ -128,35 +71,48 @@ class G1AdaptiveIHOPControl : public G1IHOPControl { size_t _last_unrestrained_young_size; // Get a new prediction bounded below by zero from the given sequence. - double predict(TruncatedSeq const* seq) const; + double predict(const TruncatedSeq* seq) const; bool have_enough_data_for_prediction() const; + double last_marking_length_s() const; // The "actual" target threshold the algorithm wants to keep during and at the // end of marking. This is typically lower than the requested threshold, as the // algorithm needs to consider restrictions by the environment. size_t actual_target_threshold() const; - // This method calculates the old gen allocation rate based on the net survived - // bytes that are allocated in the old generation in the last mutator period. - double last_mutator_period_old_allocation_rate() const; - protected: - virtual double last_marking_length_s() const { return _marking_times_s.last(); } - - virtual void print_log(size_t non_young_occupancy); - virtual void send_trace_event(G1NewTracer* tracer, size_t non_young_occupancy); + void print_log(size_t non_young_occupancy); + void send_trace_event(G1NewTracer* tracer, size_t non_young_occupancy); public: - G1AdaptiveIHOPControl(double ihop_percent, - G1OldGenAllocationTracker const* old_gen_alloc_tracker, - G1Predictions const* predictor, - 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. + G1IHOPControl(double ihop_percent, + const G1OldGenAllocationTracker* old_gen_alloc_tracker, + bool adaptive, + const G1Predictions* predictor, + size_t heap_reserve_percent, + size_t heap_waste_percent); - virtual size_t get_conc_mark_start_threshold(); + // Adjust target occupancy. + void update_target_occupancy(size_t new_target_occupancy); - virtual void update_allocation_info(double allocation_time_s, size_t additional_buffer_size); - virtual void update_marking_length(double marking_length_s); + // Update information about time during which allocations in the Java heap occurred, + // how large these allocations were in bytes, and an additional buffer. + // The allocations should contain any amount of space made unusable for further + // allocation, e.g. any waste caused by TLAB allocation, space at the end of + // humongous objects that can not be used for allocation, etc. + // 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. + void update_allocation_info(double allocation_time_s, size_t additional_buffer_size); + + // Update the time spent in the mutator beginning from the end of concurrent start to + // the first mixed gc. + void update_marking_length(double marking_length_s); + + // Get the current non-young occupancy at which concurrent marking should start. + size_t get_conc_mark_start_threshold(); + + void report_statistics(G1NewTracer* tracer, size_t non_young_occupancy); }; #endif // SHARE_GC_G1_G1IHOPCONTROL_HPP diff --git a/src/hotspot/share/gc/g1/g1OldGenAllocationTracker.hpp b/src/hotspot/share/gc/g1/g1OldGenAllocationTracker.hpp index 265c7029e14..aa5e3c6c942 100644 --- a/src/hotspot/share/gc/g1/g1OldGenAllocationTracker.hpp +++ b/src/hotspot/share/gc/g1/g1OldGenAllocationTracker.hpp @@ -28,8 +28,6 @@ #include "gc/g1/g1HeapRegion.hpp" #include "memory/allocation.hpp" -class G1AdaptiveIHOPControl; - // Track allocation details in the old generation. class G1OldGenAllocationTracker : public CHeapObj { // Total number of bytes allocated in the old generation at the end diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 828782d21eb..6eef6cbfa87 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -1025,15 +1025,12 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar G1IHOPControl* G1Policy::create_ihop_control(const G1OldGenAllocationTracker* old_gen_alloc_tracker, const G1Predictions* predictor) { - if (G1UseAdaptiveIHOP) { - return new G1AdaptiveIHOPControl(InitiatingHeapOccupancyPercent, - old_gen_alloc_tracker, - predictor, - G1ReservePercent, - G1HeapWastePercent); - } else { - return new G1StaticIHOPControl(InitiatingHeapOccupancyPercent, old_gen_alloc_tracker); - } + return new G1IHOPControl(InitiatingHeapOccupancyPercent, + old_gen_alloc_tracker, + G1UseAdaptiveIHOP, + predictor, + G1ReservePercent, + G1HeapWastePercent); } bool G1Policy::update_ihop_prediction(double mutator_time_s, diff --git a/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp b/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp index af6c5513e49..ff661fde00d 100644 --- a/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp @@ -62,16 +62,16 @@ static void test_update_humongous(G1IHOPControl* ctrl, } // @requires UseG1GC -TEST_VM(G1StaticIHOPControl, simple) { +TEST_VM(G1IHOPControl, static_simple) { // Test requires G1 if (!UseG1GC) { return; } - + const bool is_adaptive = false; const size_t initial_ihop = 45; G1OldGenAllocationTracker alloc_tracker; - G1StaticIHOPControl ctrl(initial_ihop, &alloc_tracker); + G1IHOPControl ctrl(initial_ihop, &alloc_tracker, is_adaptive, nullptr, 0, 0); ctrl.update_target_occupancy(100); size_t threshold = ctrl.get_conc_mark_start_threshold(); @@ -99,12 +99,13 @@ TEST_VM(G1StaticIHOPControl, simple) { } // @requires UseG1GC -TEST_VM(G1AdaptiveIHOPControl, simple) { +TEST_VM(G1IHOPControl, adaptive_simple) { // Test requires G1 if (!UseG1GC) { return; } + const bool is_adaptive = true; const size_t initial_threshold = 45; const size_t young_size = 10; const size_t target_size = 100; @@ -114,7 +115,7 @@ TEST_VM(G1AdaptiveIHOPControl, simple) { G1OldGenAllocationTracker alloc_tracker; G1Predictions pred(0.95); - G1AdaptiveIHOPControl ctrl(initial_threshold, &alloc_tracker, &pred, 0, 0); + G1IHOPControl ctrl(initial_threshold, &alloc_tracker, is_adaptive, &pred, 0, 0); ctrl.update_target_occupancy(target_size); // First "load". @@ -177,12 +178,13 @@ TEST_VM(G1AdaptiveIHOPControl, simple) { EXPECT_GT(threshold, settled_ihop3); } -TEST_VM(G1AdaptiveIHOPControl, humongous) { +TEST_VM(G1IHOPControl, adaptive_humongous) { // Test requires G1 if (!UseG1GC) { return; } + const bool is_adaptive = true; const size_t initial_threshold = 45; const size_t young_size = 10; const size_t target_size = 100; @@ -191,7 +193,7 @@ TEST_VM(G1AdaptiveIHOPControl, humongous) { G1OldGenAllocationTracker alloc_tracker; G1Predictions pred(0.95); - G1AdaptiveIHOPControl ctrl(initial_threshold, &alloc_tracker, &pred, 0, 0); + G1IHOPControl ctrl(initial_threshold, &alloc_tracker, is_adaptive, &pred, 0, 0); ctrl.update_target_occupancy(target_size); size_t old_bytes = 100; @@ -213,7 +215,7 @@ TEST_VM(G1AdaptiveIHOPControl, humongous) { EXPECT_EQ(threshold, target_threshold); // Load 2 - G1AdaptiveIHOPControl ctrl2(initial_threshold, &alloc_tracker, &pred, 0, 0); + G1IHOPControl ctrl2(initial_threshold, &alloc_tracker, is_adaptive, &pred, 0, 0); ctrl2.update_target_occupancy(target_size); test_update_humongous(&ctrl2, &alloc_tracker, duration, old_bytes, humongous_bytes, humongous_bytes_after_gc, young_size, marking_time); @@ -229,7 +231,7 @@ TEST_VM(G1AdaptiveIHOPControl, humongous) { // Load 3 humongous_bytes_after_last_gc = humongous_bytes_after_gc; humongous_bytes_after_gc = 50; - G1AdaptiveIHOPControl ctrl3(initial_threshold, &alloc_tracker, &pred, 0, 0); + G1IHOPControl ctrl3(initial_threshold, &alloc_tracker, is_adaptive, &pred, 0, 0); ctrl3.update_target_occupancy(target_size); test_update_humongous(&ctrl3, &alloc_tracker, duration, old_bytes, humongous_bytes, humongous_bytes_after_gc, young_size, marking_time);