8248322: G1: Refactor full collection sizing code
Reviewed-by: iwalulya, kbarrett
This commit is contained in:
parent
65b23ca67a
commit
59e3ebb4a5
@ -1143,77 +1143,15 @@ void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
|
||||
void G1CollectedHeap::resize_heap_if_necessary() {
|
||||
assert_at_safepoint_on_vm_thread();
|
||||
|
||||
// Capacity, free and used after the GC counted as full regions to
|
||||
// include the waste in the following calculations.
|
||||
const size_t capacity_after_gc = capacity();
|
||||
const size_t used_after_gc = capacity_after_gc - unused_committed_regions_in_bytes();
|
||||
bool should_expand;
|
||||
size_t resize_amount = _heap_sizing_policy->full_collection_resize_amount(should_expand);
|
||||
|
||||
// This is enforced in arguments.cpp.
|
||||
assert(MinHeapFreeRatio <= MaxHeapFreeRatio,
|
||||
"otherwise the code below doesn't make sense");
|
||||
|
||||
// We don't have floating point command-line arguments
|
||||
const double minimum_free_percentage = (double) MinHeapFreeRatio / 100.0;
|
||||
const double maximum_used_percentage = 1.0 - minimum_free_percentage;
|
||||
const double maximum_free_percentage = (double) MaxHeapFreeRatio / 100.0;
|
||||
const double minimum_used_percentage = 1.0 - maximum_free_percentage;
|
||||
|
||||
// We have to be careful here as these two calculations can overflow
|
||||
// 32-bit size_t's.
|
||||
double used_after_gc_d = (double) used_after_gc;
|
||||
double minimum_desired_capacity_d = used_after_gc_d / maximum_used_percentage;
|
||||
double maximum_desired_capacity_d = used_after_gc_d / minimum_used_percentage;
|
||||
|
||||
// Let's make sure that they are both under the max heap size, which
|
||||
// by default will make them fit into a size_t.
|
||||
double desired_capacity_upper_bound = (double) MaxHeapSize;
|
||||
minimum_desired_capacity_d = MIN2(minimum_desired_capacity_d,
|
||||
desired_capacity_upper_bound);
|
||||
maximum_desired_capacity_d = MIN2(maximum_desired_capacity_d,
|
||||
desired_capacity_upper_bound);
|
||||
|
||||
// We can now safely turn them into size_t's.
|
||||
size_t minimum_desired_capacity = (size_t) minimum_desired_capacity_d;
|
||||
size_t maximum_desired_capacity = (size_t) maximum_desired_capacity_d;
|
||||
|
||||
// This assert only makes sense here, before we adjust them
|
||||
// with respect to the min and max heap size.
|
||||
assert(minimum_desired_capacity <= maximum_desired_capacity,
|
||||
"minimum_desired_capacity = " SIZE_FORMAT ", "
|
||||
"maximum_desired_capacity = " SIZE_FORMAT,
|
||||
minimum_desired_capacity, maximum_desired_capacity);
|
||||
|
||||
// Should not be greater than the heap max size. No need to adjust
|
||||
// it with respect to the heap min size as it's a lower bound (i.e.,
|
||||
// we'll try to make the capacity larger than it, not smaller).
|
||||
minimum_desired_capacity = MIN2(minimum_desired_capacity, MaxHeapSize);
|
||||
// Should not be less than the heap min size. No need to adjust it
|
||||
// with respect to the heap max size as it's an upper bound (i.e.,
|
||||
// we'll try to make the capacity smaller than it, not greater).
|
||||
maximum_desired_capacity = MAX2(maximum_desired_capacity, MinHeapSize);
|
||||
|
||||
if (capacity_after_gc < minimum_desired_capacity) {
|
||||
// Don't expand unless it's significant
|
||||
size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
|
||||
|
||||
log_debug(gc, ergo, heap)("Attempt heap expansion (capacity lower than min desired capacity). "
|
||||
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B live: " SIZE_FORMAT "B "
|
||||
"min_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
|
||||
capacity_after_gc, used_after_gc, used(), minimum_desired_capacity, MinHeapFreeRatio);
|
||||
|
||||
expand(expand_bytes, _workers);
|
||||
|
||||
// No expansion, now see if we want to shrink
|
||||
} else if (capacity_after_gc > maximum_desired_capacity) {
|
||||
// Capacity too large, compute shrinking size
|
||||
size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity;
|
||||
|
||||
log_debug(gc, ergo, heap)("Attempt heap shrinking (capacity higher than max desired capacity). "
|
||||
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B live: " SIZE_FORMAT "B "
|
||||
"maximum_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
|
||||
capacity_after_gc, used_after_gc, used(), maximum_desired_capacity, MaxHeapFreeRatio);
|
||||
|
||||
shrink(shrink_bytes);
|
||||
if (resize_amount == 0) {
|
||||
return;
|
||||
} else if (should_expand) {
|
||||
expand(resize_amount, _workers);
|
||||
} else {
|
||||
shrink(resize_amount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2939,7 +2877,7 @@ void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType
|
||||
}
|
||||
|
||||
void G1CollectedHeap::expand_heap_after_young_collection(){
|
||||
size_t expand_bytes = _heap_sizing_policy->expansion_amount();
|
||||
size_t expand_bytes = _heap_sizing_policy->young_collection_expansion_amount();
|
||||
if (expand_bytes > 0) {
|
||||
// No need for an ergo logging here,
|
||||
// expansion_amount() does this when it returns a value > 0.
|
||||
|
@ -732,7 +732,7 @@ private:
|
||||
|
||||
// Shrink the garbage-first heap by at most the given size (in bytes!).
|
||||
// (Rounds down to a HeapRegion boundary.)
|
||||
void shrink(size_t expand_bytes);
|
||||
void shrink(size_t shrink_bytes);
|
||||
void shrink_helper(size_t expand_bytes);
|
||||
|
||||
#if TASKQUEUE_STATS
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -82,7 +82,7 @@ static void log_expansion(double short_term_pause_time_ratio,
|
||||
resize_bytes);
|
||||
}
|
||||
|
||||
size_t G1HeapSizingPolicy::expansion_amount() {
|
||||
size_t G1HeapSizingPolicy::young_collection_expansion_amount() {
|
||||
assert(GCTimeRatio > 0, "must be");
|
||||
|
||||
double long_term_pause_time_ratio = _analytics->long_term_pause_time_ratio();
|
||||
@ -195,3 +195,74 @@ size_t G1HeapSizingPolicy::expansion_amount() {
|
||||
|
||||
return expand_bytes;
|
||||
}
|
||||
|
||||
static size_t target_heap_capacity(size_t used_bytes, uintx free_ratio) {
|
||||
const double desired_free_percentage = (double) free_ratio / 100.0;
|
||||
const double desired_used_percentage = 1.0 - desired_free_percentage;
|
||||
|
||||
// We have to be careful here as these two calculations can overflow
|
||||
// 32-bit size_t's.
|
||||
double used_bytes_d = (double) used_bytes;
|
||||
double desired_capacity_d = used_bytes_d / desired_used_percentage;
|
||||
// Let's make sure that they are both under the max heap size, which
|
||||
// by default will make it fit into a size_t.
|
||||
double desired_capacity_upper_bound = (double) MaxHeapSize;
|
||||
desired_capacity_d = MIN2(desired_capacity_d, desired_capacity_upper_bound);
|
||||
// We can now safely turn it into size_t's.
|
||||
return (size_t) desired_capacity_d;
|
||||
}
|
||||
|
||||
size_t G1HeapSizingPolicy::full_collection_resize_amount(bool& expand) {
|
||||
// Capacity, free and used after the GC counted as full regions to
|
||||
// include the waste in the following calculations.
|
||||
const size_t capacity_after_gc = _g1h->capacity();
|
||||
const size_t used_after_gc = capacity_after_gc - _g1h->unused_committed_regions_in_bytes();
|
||||
|
||||
size_t minimum_desired_capacity = target_heap_capacity(used_after_gc, MinHeapFreeRatio);
|
||||
size_t maximum_desired_capacity = target_heap_capacity(used_after_gc, MaxHeapFreeRatio);
|
||||
|
||||
// This assert only makes sense here, before we adjust them
|
||||
// with respect to the min and max heap size.
|
||||
assert(minimum_desired_capacity <= maximum_desired_capacity,
|
||||
"minimum_desired_capacity = " SIZE_FORMAT ", "
|
||||
"maximum_desired_capacity = " SIZE_FORMAT,
|
||||
minimum_desired_capacity, maximum_desired_capacity);
|
||||
|
||||
// Should not be greater than the heap max size. No need to adjust
|
||||
// it with respect to the heap min size as it's a lower bound (i.e.,
|
||||
// we'll try to make the capacity larger than it, not smaller).
|
||||
minimum_desired_capacity = MIN2(minimum_desired_capacity, MaxHeapSize);
|
||||
// Should not be less than the heap min size. No need to adjust it
|
||||
// with respect to the heap max size as it's an upper bound (i.e.,
|
||||
// we'll try to make the capacity smaller than it, not greater).
|
||||
maximum_desired_capacity = MAX2(maximum_desired_capacity, MinHeapSize);
|
||||
|
||||
// Don't expand unless it's significant; prefer expansion to shrinking.
|
||||
if (capacity_after_gc < minimum_desired_capacity) {
|
||||
size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
|
||||
|
||||
log_debug(gc, ergo, heap)("Attempt heap expansion (capacity lower than min desired capacity). "
|
||||
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B live: " SIZE_FORMAT "B "
|
||||
"min_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
|
||||
capacity_after_gc, used_after_gc, _g1h->used(), minimum_desired_capacity, MinHeapFreeRatio);
|
||||
|
||||
expand = true;
|
||||
return expand_bytes;
|
||||
// No expansion, now see if we want to shrink
|
||||
} else if (capacity_after_gc > maximum_desired_capacity) {
|
||||
// Capacity too large, compute shrinking size
|
||||
size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity;
|
||||
|
||||
log_debug(gc, ergo, heap)("Attempt heap shrinking (capacity higher than max desired capacity). "
|
||||
"Capacity: " SIZE_FORMAT "B occupancy: " SIZE_FORMAT "B live: " SIZE_FORMAT "B "
|
||||
"maximum_desired_capacity: " SIZE_FORMAT "B (" UINTX_FORMAT " %%)",
|
||||
capacity_after_gc, used_after_gc, _g1h->used(), maximum_desired_capacity, MaxHeapFreeRatio);
|
||||
|
||||
expand = false;
|
||||
return shrink_bytes;
|
||||
}
|
||||
|
||||
expand = true; // Does not matter.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -54,8 +54,11 @@ public:
|
||||
|
||||
// If an expansion would be appropriate, because recent GC overhead had
|
||||
// exceeded the desired limit, return an amount to expand by.
|
||||
size_t expansion_amount();
|
||||
size_t young_collection_expansion_amount();
|
||||
|
||||
// Returns the amount of bytes to resize the heap; if expand is set, the heap
|
||||
// should by expanded by that amount, shrunk otherwise.
|
||||
size_t full_collection_resize_amount(bool& expand);
|
||||
// Clear ratio tracking data used by expansion_amount().
|
||||
void clear_ratio_check_data();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user