From c0da29324160e2cb866aea80f078ca1fba322525 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 26 Sep 2025 11:22:06 +0200 Subject: [PATCH] * updates --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 2 +- src/hotspot/share/gc/g1/g1IHOPControl.cpp | 69 ++++++++++++++------- src/hotspot/share/gc/g1/g1IHOPControl.hpp | 38 ++++++++---- src/hotspot/share/gc/g1/g1Policy.cpp | 2 +- src/hotspot/share/gc/g1/g1Trace.cpp | 16 +++++ src/hotspot/share/gc/g1/g1Trace.hpp | 8 +++ src/hotspot/share/jfr/metadata/metadata.xml | 4 ++ 7 files changed, 104 insertions(+), 35 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 4bd4a986927..454bc40a58b 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2220,7 +2220,7 @@ size_t G1CollectedHeap::min_capacity() const { } size_t G1CollectedHeap::soft_max_capacity() const { - return clamp(align_up(SoftMaxHeapSize, HeapRegion::GrainBytes), HeapAlignment, max_capacity()); + return clamp(align_up(AtomicAccess::load(&SoftMaxHeapSize), G1HeapRegion::GrainBytes), HeapAlignment, max_capacity()); } void G1CollectedHeap::prepare_for_verify() { diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.cpp b/src/hotspot/share/gc/g1/g1IHOPControl.cpp index d7fa826e0d0..2cdfcfab897 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.cpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.cpp @@ -30,18 +30,37 @@ G1IHOPControl::G1IHOPControl(double initial_ihop_percent, G1OldGenAllocationTracker const* old_gen_alloc_tracker) : + _current_heap_size(0), + _current_soft_max_heap_size(0), _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); } -void G1IHOPControl::update_target_occupancy(size_t new_target_occupancy) { +size_t G1IHOPControl::target_occupancy() const { + return MIN2(_current_heap_size, _current_soft_max_heap_size); +} + +size_t G1IHOPControl::current_heap_size() const { + return _current_heap_size; +} + +size_t G1IHOPControl::current_soft_max_heap_size() const { + return _current_soft_max_heap_size; +} + +size_t G1IHOPControl::get_conc_mark_start_threshold() { + _current_soft_max_heap_size = G1CollectedHeap::heap()->soft_max_capacity(); + return get_conc_mark_start_threshold_internal(); +} + +void G1IHOPControl::update_heap_size(size_t new_heap_size) { log_debug(gc, ihop)("Target occupancy update: old: %zuB, new: %zuB", - _target_occupancy, new_target_occupancy); - _target_occupancy = new_target_occupancy; + _current_heap_size, new_heap_size); + _current_heap_size = new_heap_size; + _current_soft_max_heap_size = G1CollectedHeap::heap()->soft_max_capacity(); } void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t additional_buffer_size) { @@ -51,14 +70,16 @@ void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t addi } 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(); - log_debug(gc, ihop)("Basic information (value update), threshold: %zuB (%1.2f), target occupancy: %zuB, current occupancy: %zuB, " + assert(_current_heap_size > 0, "Heap size occupancy still not updated yet."); + size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold_internal(); + log_debug(gc, ihop)("Basic information (value update), threshold: %zuB (%1.2f), target occupancy: %zuB, heap used: %zuB, heap size: %zuB, soft max size: %zuB, " "recent allocation size: %zuB, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms", cur_conc_mark_start_threshold, - percent_of(cur_conc_mark_start_threshold, _target_occupancy), - _target_occupancy, + percent_of(cur_conc_mark_start_threshold, target_occupancy()), + target_occupancy(), G1CollectedHeap::heap()->used(), + current_heap_size(), + current_soft_max_heap_size(), _old_gen_alloc_tracker->last_period_old_gen_bytes(), _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, @@ -66,10 +87,12 @@ void G1IHOPControl::print() { } 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(), - _target_occupancy, + assert(_current_heap_size > 0, "Heap size still not updated yet."); + tracer->report_basic_ihop_statistics(get_conc_mark_start_threshold_internal(), + target_occupancy(), G1CollectedHeap::heap()->used(), + current_heap_size(), + current_soft_max_heap_size(), _old_gen_alloc_tracker->last_period_old_gen_bytes(), _last_allocation_time_s, last_marking_length_s()); @@ -97,7 +120,7 @@ G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent, } size_t G1AdaptiveIHOPControl::actual_target_threshold() const { - guarantee(_target_occupancy > 0, "Target occupancy still not updated yet."); + guarantee(current_heap_size() > 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 @@ -109,8 +132,8 @@ size_t G1AdaptiveIHOPControl::actual_target_threshold() const { double safe_total_heap_percentage = MIN2((double)(_heap_reserve_percent + _heap_waste_percent), 100.0); return (size_t)MIN2( - G1CollectedHeap::heap()->soft_max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, - _target_occupancy * (100.0 - _heap_waste_percent) / 100.0 + G1CollectedHeap::heap()->max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, + target_occupancy() * (100.0 - _heap_waste_percent) / 100.0 ); } @@ -123,7 +146,7 @@ bool G1AdaptiveIHOPControl::have_enough_data_for_prediction() const { ((size_t)_allocation_rate_s.num() >= G1AdaptiveIHOPNumInitialSamples); } -size_t G1AdaptiveIHOPControl::get_conc_mark_start_threshold() { +size_t G1AdaptiveIHOPControl::get_conc_mark_start_threshold_internal() { if (have_enough_data_for_prediction()) { double pred_marking_time = predict(&_marking_times_s); double pred_promotion_rate = predict(&_allocation_rate_s); @@ -142,7 +165,7 @@ size_t G1AdaptiveIHOPControl::get_conc_mark_start_threshold() { return predicted_initiating_threshold; } else { // Use the initial value. - return (size_t)(_initial_ihop_percent * _target_occupancy / 100.0); + return (size_t)(_initial_ihop_percent * target_occupancy() / 100.0); } } @@ -169,12 +192,14 @@ void G1AdaptiveIHOPControl::print() { G1IHOPControl::print(); size_t actual_target = actual_target_threshold(); log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: %zuB (%1.2f), internal target occupancy: %zuB, " - "occupancy: %zuB, additional buffer size: %zuB, predicted old gen allocation rate: %1.2fB/s, " + "occupancy: %zuB, heap size: %zuB, soft max size: %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_target), + get_conc_mark_start_threshold_internal(), + percent_of(get_conc_mark_start_threshold_internal(), actual_target), actual_target, G1CollectedHeap::heap()->used(), + current_heap_size(), + current_soft_max_heap_size(), _last_unrestrained_young_size, predict(&_allocation_rate_s), predict(&_marking_times_s) * 1000.0, @@ -183,9 +208,11 @@ void G1AdaptiveIHOPControl::print() { void G1AdaptiveIHOPControl::send_trace_event(G1NewTracer* tracer) { G1IHOPControl::send_trace_event(tracer); - tracer->report_adaptive_ihop_statistics(get_conc_mark_start_threshold(), + tracer->report_adaptive_ihop_statistics(get_conc_mark_start_threshold_internal(), actual_target_threshold(), G1CollectedHeap::heap()->used(), + current_heap_size(), + current_soft_max_heap_size(), _last_unrestrained_young_size, predict(&_allocation_rate_s), predict(&_marking_times_s), diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.hpp b/src/hotspot/share/gc/g1/g1IHOPControl.hpp index 507fbb269d1..06b2ab13266 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.hpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -36,12 +36,13 @@ class G1NewTracer; // concurrent marking should start. This heap usage threshold should be relative // to old gen size. class G1IHOPControl : public CHeapObj { - protected: + // Current values of heap/SoftMaxHeapSize variables used for calculations. + size_t _current_heap_size; + size_t _current_soft_max_heap_size; + +protected: // 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; // Most recent complete mutator allocation period in seconds. double _last_allocation_time_s; @@ -52,6 +53,19 @@ class G1IHOPControl : public CHeapObj { // at the first heap expansion. G1IHOPControl(double ihop_percent, G1OldGenAllocationTracker const* old_gen_alloc_tracker); + // The target maximum occupancy of the heap. The target occupancy is the number + // of bytes when marking should be finished and reclaim started. + // This is a function of current heap size and external SoftMaxHeapSize goal. + size_t target_occupancy() const; + + size_t current_heap_size() const; + size_t current_soft_max_heap_size() const; + + // Same as get_conc_mark_start_threshold(), but using the internally stored variables + // to calculate to achieve some consistency when called multiple times for various + // reasons. + virtual size_t get_conc_mark_start_threshold_internal() = 0; + // 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; @@ -59,10 +73,10 @@ class G1IHOPControl : public CHeapObj { virtual ~G1IHOPControl() { } // 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(); - // Adjust target occupancy. - virtual void update_target_occupancy(size_t new_target_occupancy); + // Adjust current heap size. + virtual void update_heap_size(size_t new_heap_size); // 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 @@ -91,9 +105,9 @@ class G1StaticIHOPControl : public G1IHOPControl { 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); + size_t get_conc_mark_start_threshold_internal() { + guarantee(current_heap_size() > 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) { @@ -146,7 +160,7 @@ class G1AdaptiveIHOPControl : public G1IHOPControl { 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. - virtual size_t get_conc_mark_start_threshold(); + virtual size_t get_conc_mark_start_threshold_internal(); virtual void update_allocation_info(double allocation_time_s, size_t additional_buffer_size); virtual void update_marking_length(double marking_length_s); diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 88a2689e68f..c7ae56dab32 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -164,7 +164,7 @@ void G1Policy::record_new_heap_size(uint new_number_of_regions) { _young_gen_sizer.heap_size_changed(new_number_of_regions); - _ihop_control->update_target_occupancy(new_number_of_regions * G1HeapRegion::GrainBytes); + _ihop_control->update_heap_size(new_number_of_regions * G1HeapRegion::GrainBytes); } uint G1Policy::calculate_desired_eden_length_by_mmu() const { diff --git a/src/hotspot/share/gc/g1/g1Trace.cpp b/src/hotspot/share/gc/g1/g1Trace.cpp index 6c9a87e4d98..912f34ec96b 100644 --- a/src/hotspot/share/gc/g1/g1Trace.cpp +++ b/src/hotspot/share/gc/g1/g1Trace.cpp @@ -99,12 +99,16 @@ void G1NewTracer::report_evacuation_statistics(const G1EvacSummary& young_summar void G1NewTracer::report_basic_ihop_statistics(size_t threshold, size_t target_ccupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t last_allocation_size, double last_allocation_duration, double last_marking_length) { send_basic_ihop_statistics(threshold, target_ccupancy, current_occupancy, + current_max_occupancy, + soft_max_heap_size, last_allocation_size, last_allocation_duration, last_marking_length); @@ -113,6 +117,8 @@ void G1NewTracer::report_basic_ihop_statistics(size_t threshold, void G1NewTracer::report_adaptive_ihop_statistics(size_t threshold, size_t internal_target_occupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t additional_buffer_size, double predicted_allocation_rate, double predicted_marking_length, @@ -120,6 +126,8 @@ void G1NewTracer::report_adaptive_ihop_statistics(size_t threshold, send_adaptive_ihop_statistics(threshold, internal_target_occupancy, current_occupancy, + current_max_occupancy, + soft_max_heap_size, additional_buffer_size, predicted_allocation_rate, predicted_marking_length, @@ -207,6 +215,8 @@ void G1NewTracer::send_old_evacuation_statistics(const G1EvacSummary& summary) c void G1NewTracer::send_basic_ihop_statistics(size_t threshold, size_t target_occupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t last_allocation_size, double last_allocation_duration, double last_marking_length) { @@ -217,6 +227,8 @@ void G1NewTracer::send_basic_ihop_statistics(size_t threshold, evt.set_targetOccupancy(target_occupancy); evt.set_thresholdPercentage(target_occupancy > 0 ? ((double)threshold / target_occupancy) : 0.0); evt.set_currentOccupancy(current_occupancy); + evt.set_currentMaxOccupancy(current_max_occupancy); + evt.set_currentSoftMaxHeapSize(soft_max_heap_size); evt.set_recentMutatorAllocationSize(last_allocation_size); evt.set_recentMutatorDuration(last_allocation_duration * MILLIUNITS); evt.set_recentAllocationRate(last_allocation_duration != 0.0 ? last_allocation_size / last_allocation_duration : 0.0); @@ -228,6 +240,8 @@ void G1NewTracer::send_basic_ihop_statistics(size_t threshold, void G1NewTracer::send_adaptive_ihop_statistics(size_t threshold, size_t internal_target_occupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t additional_buffer_size, double predicted_allocation_rate, double predicted_marking_length, @@ -239,6 +253,8 @@ void G1NewTracer::send_adaptive_ihop_statistics(size_t threshold, evt.set_thresholdPercentage(internal_target_occupancy > 0 ? ((double)threshold / internal_target_occupancy) : 0.0); evt.set_ihopTargetOccupancy(internal_target_occupancy); evt.set_currentOccupancy(current_occupancy); + evt.set_currentMaxOccupancy(current_max_occupancy); + evt.set_currentSoftMaxHeapSize(soft_max_heap_size); evt.set_additionalBufferSize(additional_buffer_size); evt.set_predictedAllocationRate(predicted_allocation_rate); evt.set_predictedMarkingDuration(predicted_marking_length * MILLIUNITS); diff --git a/src/hotspot/share/gc/g1/g1Trace.hpp b/src/hotspot/share/gc/g1/g1Trace.hpp index 025a1c3fe95..fbf6598beb5 100644 --- a/src/hotspot/share/gc/g1/g1Trace.hpp +++ b/src/hotspot/share/gc/g1/g1Trace.hpp @@ -53,12 +53,16 @@ public: void report_basic_ihop_statistics(size_t threshold, size_t target_occupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t last_allocation_size, double last_allocation_duration, double last_marking_length); void report_adaptive_ihop_statistics(size_t threshold, size_t internal_target_occupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t additional_buffer_size, double predicted_allocation_rate, double predicted_marking_length, @@ -74,12 +78,16 @@ private: void send_basic_ihop_statistics(size_t threshold, size_t target_occupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t last_allocation_size, double last_allocation_duration, double last_marking_length); void send_adaptive_ihop_statistics(size_t threshold, size_t internal_target_occupancy, size_t current_occupancy, + size_t current_max_occupancy, + size_t soft_max_heap_size, size_t additional_buffer_size, double predicted_allocation_rate, double predicted_marking_length, diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 060a78f13e7..94e7f6f16c2 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -499,6 +499,8 @@ + + @@ -513,6 +515,8 @@ + +