mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-16 00:54:38 +02:00
6929868: G1: introduce min / max young gen size bounds
Make G1 handle young gen size command line flags more consistently Reviewed-by: tonyp, jwilhelm
This commit is contained in:
parent
d96de580b6
commit
0be11c915c
3 changed files with 89 additions and 31 deletions
|
@ -1682,7 +1682,7 @@ bool G1CollectedHeap::expand(size_t expand_bytes) {
|
||||||
}
|
}
|
||||||
assert(curr == mr.end(), "post-condition");
|
assert(curr == mr.end(), "post-condition");
|
||||||
}
|
}
|
||||||
g1_policy()->calculate_reserve(n_regions());
|
g1_policy()->record_new_heap_size(n_regions());
|
||||||
} else {
|
} else {
|
||||||
ergo_verbose0(ErgoHeapSizing,
|
ergo_verbose0(ErgoHeapSizing,
|
||||||
"did not expand the heap",
|
"did not expand the heap",
|
||||||
|
@ -1733,7 +1733,7 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
|
||||||
_expansion_regions += num_regions_deleted;
|
_expansion_regions += num_regions_deleted;
|
||||||
update_committed_space(old_end, new_end);
|
update_committed_space(old_end, new_end);
|
||||||
HeapRegionRemSet::shrink_heap(n_regions());
|
HeapRegionRemSet::shrink_heap(n_regions());
|
||||||
g1_policy()->calculate_reserve(n_regions());
|
g1_policy()->record_new_heap_size(n_regions());
|
||||||
} else {
|
} else {
|
||||||
ergo_verbose0(ErgoHeapSizing,
|
ergo_verbose0(ErgoHeapSizing,
|
||||||
"did not shrink the heap",
|
"did not shrink the heap",
|
||||||
|
@ -3525,6 +3525,19 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||||
|
|
||||||
init_mutator_alloc_region();
|
init_mutator_alloc_region();
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t expand_bytes = g1_policy()->expansion_amount();
|
||||||
|
if (expand_bytes > 0) {
|
||||||
|
size_t bytes_before = capacity();
|
||||||
|
if (!expand(expand_bytes)) {
|
||||||
|
// We failed to expand the heap so let's verify that
|
||||||
|
// committed/uncommitted amount match the backing store
|
||||||
|
assert(capacity() == _g1_storage.committed_size(), "committed size mismatch");
|
||||||
|
assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double end_time_sec = os::elapsedTime();
|
double end_time_sec = os::elapsedTime();
|
||||||
double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS;
|
double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS;
|
||||||
g1_policy()->record_pause_time_ms(pause_time_ms);
|
g1_policy()->record_pause_time_ms(pause_time_ms);
|
||||||
|
|
|
@ -146,6 +146,7 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
||||||
_stop_world_start(0.0),
|
_stop_world_start(0.0),
|
||||||
_all_stop_world_times_ms(new NumberSeq()),
|
_all_stop_world_times_ms(new NumberSeq()),
|
||||||
_all_yield_times_ms(new NumberSeq()),
|
_all_yield_times_ms(new NumberSeq()),
|
||||||
|
_using_new_ratio_calculations(false),
|
||||||
|
|
||||||
_all_mod_union_times_ms(new NumberSeq()),
|
_all_mod_union_times_ms(new NumberSeq()),
|
||||||
|
|
||||||
|
@ -430,7 +431,7 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
||||||
"it's been updated to %u", reserve_perc);
|
"it's been updated to %u", reserve_perc);
|
||||||
}
|
}
|
||||||
_reserve_factor = (double) reserve_perc / 100.0;
|
_reserve_factor = (double) reserve_perc / 100.0;
|
||||||
// This will be set in calculate_reserve() when the heap is expanded
|
// This will be set when the heap is expanded
|
||||||
// for the first time during initialization.
|
// for the first time during initialization.
|
||||||
_reserve_regions = 0;
|
_reserve_regions = 0;
|
||||||
|
|
||||||
|
@ -458,16 +459,15 @@ void G1CollectorPolicy::initialize_flags() {
|
||||||
// ParallelScavengeHeap::initialize()). We might change this in the
|
// ParallelScavengeHeap::initialize()). We might change this in the
|
||||||
// future, but it's a good start.
|
// future, but it's a good start.
|
||||||
class G1YoungGenSizer : public TwoGenerationCollectorPolicy {
|
class G1YoungGenSizer : public TwoGenerationCollectorPolicy {
|
||||||
size_t size_to_region_num(size_t byte_size) {
|
|
||||||
return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1YoungGenSizer() {
|
G1YoungGenSizer() {
|
||||||
initialize_flags();
|
initialize_flags();
|
||||||
initialize_size_info();
|
initialize_size_info();
|
||||||
}
|
}
|
||||||
|
size_t size_to_region_num(size_t byte_size) {
|
||||||
|
return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes);
|
||||||
|
}
|
||||||
size_t min_young_region_num() {
|
size_t min_young_region_num() {
|
||||||
return size_to_region_num(_min_gen0_size);
|
return size_to_region_num(_min_gen0_size);
|
||||||
}
|
}
|
||||||
|
@ -479,6 +479,13 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) {
|
||||||
|
assert(number_of_heap_regions > 0, "Heap must be initialized");
|
||||||
|
size_t young_size = number_of_heap_regions / (NewRatio + 1);
|
||||||
|
_min_desired_young_length = young_size;
|
||||||
|
_max_desired_young_length = young_size;
|
||||||
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy::init() {
|
void G1CollectorPolicy::init() {
|
||||||
// Set aside an initial future to_space.
|
// Set aside an initial future to_space.
|
||||||
_g1 = G1CollectedHeap::heap();
|
_g1 = G1CollectedHeap::heap();
|
||||||
|
@ -489,16 +496,35 @@ void G1CollectorPolicy::init() {
|
||||||
|
|
||||||
G1YoungGenSizer sizer;
|
G1YoungGenSizer sizer;
|
||||||
size_t initial_region_num = sizer.initial_young_region_num();
|
size_t initial_region_num = sizer.initial_young_region_num();
|
||||||
|
_min_desired_young_length = sizer.min_young_region_num();
|
||||||
|
_max_desired_young_length = sizer.max_young_region_num();
|
||||||
|
|
||||||
if (UseAdaptiveSizePolicy) {
|
if (FLAG_IS_CMDLINE(NewRatio)) {
|
||||||
set_adaptive_young_list_length(true);
|
if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
|
||||||
|
gclog_or_tty->print_cr("-XX:NewSize and -XX:MaxNewSize overrides -XX:NewRatio");
|
||||||
|
} else {
|
||||||
|
// Treat NewRatio as a fixed size that is only recalculated when the heap size changes
|
||||||
|
size_t heap_regions = sizer.size_to_region_num(_g1->n_regions());
|
||||||
|
update_young_list_size_using_newratio(heap_regions);
|
||||||
|
_using_new_ratio_calculations = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenCollectorPolicy guarantees that min <= initial <= max.
|
||||||
|
// Asserting here just to state that we rely on this property.
|
||||||
|
assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");
|
||||||
|
assert(initial_region_num <= _max_desired_young_length, "Initial young gen size too large");
|
||||||
|
assert(_min_desired_young_length <= initial_region_num, "Initial young gen size too small");
|
||||||
|
|
||||||
|
set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length);
|
||||||
|
if (adaptive_young_list_length()) {
|
||||||
_young_list_fixed_length = 0;
|
_young_list_fixed_length = 0;
|
||||||
} else {
|
} else {
|
||||||
set_adaptive_young_list_length(false);
|
|
||||||
_young_list_fixed_length = initial_region_num;
|
_young_list_fixed_length = initial_region_num;
|
||||||
}
|
}
|
||||||
_free_regions_at_end_of_collection = _g1->free_regions();
|
_free_regions_at_end_of_collection = _g1->free_regions();
|
||||||
update_young_list_target_length();
|
update_young_list_target_length();
|
||||||
|
_prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes;
|
||||||
|
|
||||||
// We may immediately start allocating regions and placing them on the
|
// We may immediately start allocating regions and placing them on the
|
||||||
// collection set list. Initialize the per-collection set info
|
// collection set list. Initialize the per-collection set info
|
||||||
|
@ -541,11 +567,18 @@ bool G1CollectorPolicy::predict_will_fit(size_t young_length,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy::calculate_reserve(size_t all_regions) {
|
void G1CollectorPolicy::record_new_heap_size(size_t new_number_of_regions) {
|
||||||
double reserve_regions_d = (double) all_regions * _reserve_factor;
|
// re-calculate the necessary reserve
|
||||||
|
double reserve_regions_d = (double) new_number_of_regions * _reserve_factor;
|
||||||
// We use ceiling so that if reserve_regions_d is > 0.0 (but
|
// We use ceiling so that if reserve_regions_d is > 0.0 (but
|
||||||
// smaller than 1.0) we'll get 1.
|
// smaller than 1.0) we'll get 1.
|
||||||
_reserve_regions = (size_t) ceil(reserve_regions_d);
|
_reserve_regions = (size_t) ceil(reserve_regions_d);
|
||||||
|
|
||||||
|
if (_using_new_ratio_calculations) {
|
||||||
|
// -XX:NewRatio was specified so we need to update the
|
||||||
|
// young gen length when the heap size has changed.
|
||||||
|
update_young_list_size_using_newratio(new_number_of_regions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t G1CollectorPolicy::calculate_young_list_desired_min_length(
|
size_t G1CollectorPolicy::calculate_young_list_desired_min_length(
|
||||||
|
@ -561,16 +594,16 @@ size_t G1CollectorPolicy::calculate_young_list_desired_min_length(
|
||||||
// otherwise we don't have enough info to make the prediction
|
// otherwise we don't have enough info to make the prediction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Here, we might want to also take into account any additional
|
desired_min_length += base_min_length;
|
||||||
// constraints (i.e., user-defined minimum bound). Currently, we don't.
|
// make sure we don't go below any user-defined minimum bound
|
||||||
return base_min_length + desired_min_length;
|
return MAX2(_min_desired_young_length, desired_min_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t G1CollectorPolicy::calculate_young_list_desired_max_length() {
|
size_t G1CollectorPolicy::calculate_young_list_desired_max_length() {
|
||||||
// Here, we might want to also take into account any additional
|
// Here, we might want to also take into account any additional
|
||||||
// constraints (i.e., user-defined minimum bound). Currently, we
|
// constraints (i.e., user-defined minimum bound). Currently, we
|
||||||
// effectively don't set this bound.
|
// effectively don't set this bound.
|
||||||
return _g1->n_regions();
|
return _max_desired_young_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) {
|
void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) {
|
||||||
|
@ -1699,20 +1732,26 @@ void G1CollectorPolicy::print_heap_transition() {
|
||||||
size_t used_before_gc = _cur_collection_pause_used_at_start_bytes;
|
size_t used_before_gc = _cur_collection_pause_used_at_start_bytes;
|
||||||
size_t used = _g1->used();
|
size_t used = _g1->used();
|
||||||
size_t capacity = _g1->capacity();
|
size_t capacity = _g1->capacity();
|
||||||
|
size_t eden_capacity =
|
||||||
|
(_young_list_target_length * HeapRegion::GrainBytes) - survivor_bytes;
|
||||||
|
|
||||||
gclog_or_tty->print_cr(
|
gclog_or_tty->print_cr(
|
||||||
" [Eden: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
|
" [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") "
|
||||||
"Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
|
"Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
|
||||||
"Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"
|
"Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"
|
||||||
EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]",
|
EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]",
|
||||||
EXT_SIZE_PARAMS(_eden_bytes_before_gc),
|
EXT_SIZE_PARAMS(_eden_bytes_before_gc),
|
||||||
|
EXT_SIZE_PARAMS(_prev_eden_capacity),
|
||||||
EXT_SIZE_PARAMS(eden_bytes),
|
EXT_SIZE_PARAMS(eden_bytes),
|
||||||
|
EXT_SIZE_PARAMS(eden_capacity),
|
||||||
EXT_SIZE_PARAMS(_survivor_bytes_before_gc),
|
EXT_SIZE_PARAMS(_survivor_bytes_before_gc),
|
||||||
EXT_SIZE_PARAMS(survivor_bytes),
|
EXT_SIZE_PARAMS(survivor_bytes),
|
||||||
EXT_SIZE_PARAMS(used_before_gc),
|
EXT_SIZE_PARAMS(used_before_gc),
|
||||||
EXT_SIZE_PARAMS(_capacity_before_gc),
|
EXT_SIZE_PARAMS(_capacity_before_gc),
|
||||||
EXT_SIZE_PARAMS(used),
|
EXT_SIZE_PARAMS(used),
|
||||||
EXT_SIZE_PARAMS(capacity));
|
EXT_SIZE_PARAMS(capacity));
|
||||||
|
|
||||||
|
_prev_eden_capacity = eden_capacity;
|
||||||
} else if (PrintGC) {
|
} else if (PrintGC) {
|
||||||
_g1->print_size_transition(gclog_or_tty,
|
_g1->print_size_transition(gclog_or_tty,
|
||||||
_cur_collection_pause_used_at_start_bytes,
|
_cur_collection_pause_used_at_start_bytes,
|
||||||
|
|
|
@ -185,6 +185,7 @@ protected:
|
||||||
bool _adaptive_young_list_length;
|
bool _adaptive_young_list_length;
|
||||||
size_t _young_list_target_length;
|
size_t _young_list_target_length;
|
||||||
size_t _young_list_fixed_length;
|
size_t _young_list_fixed_length;
|
||||||
|
size_t _prev_eden_capacity; // used for logging
|
||||||
|
|
||||||
// The max number of regions we can extend the eden by while the GC
|
// The max number of regions we can extend the eden by while the GC
|
||||||
// locker is active. This should be >= _young_list_target_length;
|
// locker is active. This should be >= _young_list_target_length;
|
||||||
|
@ -245,6 +246,10 @@ private:
|
||||||
|
|
||||||
TruncatedSeq* _max_conc_overhead_seq;
|
TruncatedSeq* _max_conc_overhead_seq;
|
||||||
|
|
||||||
|
bool _using_new_ratio_calculations;
|
||||||
|
size_t _min_desired_young_length; // as set on the command line or default calculations
|
||||||
|
size_t _max_desired_young_length; // as set on the command line or default calculations
|
||||||
|
|
||||||
size_t _recorded_young_regions;
|
size_t _recorded_young_regions;
|
||||||
size_t _recorded_non_young_regions;
|
size_t _recorded_non_young_regions;
|
||||||
size_t _recorded_region_num;
|
size_t _recorded_region_num;
|
||||||
|
@ -826,9 +831,8 @@ public:
|
||||||
return _all_pause_times_ms->num() + 1;
|
return _all_pause_times_ms->num() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recalculate the reserve region number. This should be called
|
// This should be called after the heap is resized.
|
||||||
// after the heap is resized.
|
void record_new_heap_size(size_t new_number_of_regions);
|
||||||
void calculate_reserve(size_t all_regions);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -841,6 +845,8 @@ protected:
|
||||||
size_t max_live_bytes);
|
size_t max_live_bytes);
|
||||||
void record_concurrent_mark_cleanup_end_work2();
|
void record_concurrent_mark_cleanup_end_work2();
|
||||||
|
|
||||||
|
void update_young_list_size_using_newratio(size_t number_of_heap_regions);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue