Skip to content

Commit b1e8c4e

Browse files
rgithubliXiaolong Peng
authored andcommitted
8372543: Shenandoah: undercalculated the available size when soft max takes effect
Reviewed-by: wkemper, kdnilsen
1 parent 3f33eaa commit b1e8c4e

13 files changed

+182
-91
lines changed

src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include "gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp"
3232
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
3333
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
34-
#include "gc/shenandoah/shenandoahFreeSet.hpp"
3534
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
3635
#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
3736
#include "logging/log.hpp"
@@ -234,11 +233,12 @@ static double saturate(double value, double min, double max) {
234233
// allocation rate computation independent.
235234
bool ShenandoahAdaptiveHeuristics::should_start_gc() {
236235
size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
237-
size_t available = _space_info->soft_available();
236+
size_t available = _space_info->soft_mutator_available();
238237
size_t allocated = _space_info->bytes_allocated_since_gc_start();
239238

240-
log_debug(gc)("should_start_gc? available: %zu, soft_max_capacity: %zu"
241-
", allocated: %zu", available, capacity, allocated);
239+
log_debug(gc, ergo)("should_start_gc calculation: available: " PROPERFMT ", soft_max_capacity: " PROPERFMT ", "
240+
"allocated_since_gc_start: " PROPERFMT,
241+
PROPERFMTARGS(available), PROPERFMTARGS(capacity), PROPERFMTARGS(allocated));
242242

243243
// Track allocation rate even if we decide to start a cycle for other reasons.
244244
double rate = _allocation_rate.sample(allocated);
@@ -252,9 +252,8 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() {
252252

253253
size_t min_threshold = min_free_threshold();
254254
if (available < min_threshold) {
255-
log_trigger("Free (%zu%s) is below minimum threshold (%zu%s)",
256-
byte_size_in_proper_unit(available), proper_unit_for_byte_size(available),
257-
byte_size_in_proper_unit(min_threshold), proper_unit_for_byte_size(min_threshold));
255+
log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")",
256+
PROPERFMTARGS(available), PROPERFMTARGS(min_threshold));
258257
accept_trigger_with_type(OTHER);
259258
return true;
260259
}

src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
#include "gc/shenandoah/heuristics/shenandoahCompactHeuristics.hpp"
2828
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
29-
#include "gc/shenandoah/shenandoahFreeSet.hpp"
3029
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
3130
#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
3231
#include "logging/log.hpp"
@@ -47,26 +46,25 @@ ShenandoahCompactHeuristics::ShenandoahCompactHeuristics(ShenandoahSpaceInfo* sp
4746
}
4847

4948
bool ShenandoahCompactHeuristics::should_start_gc() {
50-
size_t max_capacity = _space_info->max_capacity();
5149
size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
52-
size_t available = _space_info->available();
50+
size_t available = _space_info->soft_mutator_available();
51+
size_t bytes_allocated = _space_info->bytes_allocated_since_gc_start();
5352

54-
// Make sure the code below treats available without the soft tail.
55-
size_t soft_tail = max_capacity - capacity;
56-
available = (available > soft_tail) ? (available - soft_tail) : 0;
53+
log_debug(gc, ergo)("should_start_gc calculation: available: " PROPERFMT ", soft_max_capacity: " PROPERFMT ", "
54+
"allocated_since_gc_start: " PROPERFMT,
55+
PROPERFMTARGS(available), PROPERFMTARGS(capacity), PROPERFMTARGS(bytes_allocated));
5756

5857
size_t threshold_bytes_allocated = capacity / 100 * ShenandoahAllocationThreshold;
5958
size_t min_threshold = capacity / 100 * ShenandoahMinFreeThreshold;
6059

6160
if (available < min_threshold) {
62-
log_trigger("Free (%zu%s) is below minimum threshold (%zu%s)",
61+
log_trigger("Free (Soft) (%zu%s) is below minimum threshold (%zu%s)",
6362
byte_size_in_proper_unit(available), proper_unit_for_byte_size(available),
6463
byte_size_in_proper_unit(min_threshold), proper_unit_for_byte_size(min_threshold));
6564
accept_trigger();
6665
return true;
6766
}
6867

69-
size_t bytes_allocated = _space_info->bytes_allocated_since_gc_start();
7068
if (bytes_allocated > threshold_bytes_allocated) {
7169
log_trigger("Allocated since last cycle (%zu%s) is larger than allocation threshold (%zu%s)",
7270
byte_size_in_proper_unit(bytes_allocated), proper_unit_for_byte_size(bytes_allocated),

src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class ShenandoahSpaceInfo {
3838
public:
3939
virtual const char* name() const = 0;
4040
virtual size_t max_capacity() const = 0;
41-
virtual size_t soft_available() const = 0;
41+
virtual size_t soft_mutator_available() const = 0;
4242
virtual size_t available() const = 0;
4343
virtual size_t used() const = 0;
4444

src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
#include "gc/shenandoah/heuristics/shenandoahStaticHeuristics.hpp"
2828
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
29-
#include "gc/shenandoah/shenandoahFreeSet.hpp"
3029
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
3130
#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
3231
#include "logging/log.hpp"
@@ -41,20 +40,19 @@ ShenandoahStaticHeuristics::ShenandoahStaticHeuristics(ShenandoahSpaceInfo* spac
4140
ShenandoahStaticHeuristics::~ShenandoahStaticHeuristics() {}
4241

4342
bool ShenandoahStaticHeuristics::should_start_gc() {
44-
size_t max_capacity = _space_info->max_capacity();
4543
size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
46-
size_t available = _space_info->available();
44+
size_t available = _space_info->soft_mutator_available();
45+
size_t allocated = _space_info->bytes_allocated_since_gc_start();
4746

48-
// Make sure the code below treats available without the soft tail.
49-
size_t soft_tail = max_capacity - capacity;
50-
available = (available > soft_tail) ? (available - soft_tail) : 0;
47+
log_debug(gc, ergo)("should_start_gc calculation: available: " PROPERFMT ", soft_max_capacity: " PROPERFMT ", "
48+
"allocated_since_gc_start: " PROPERFMT,
49+
PROPERFMTARGS(available), PROPERFMTARGS(capacity), PROPERFMTARGS(allocated));
5150

5251
size_t threshold_available = capacity / 100 * ShenandoahMinFreeThreshold;
5352

5453
if (available < threshold_available) {
55-
log_trigger("Free (%zu%s) is below minimum threshold (%zu%s)",
56-
byte_size_in_proper_unit(available), proper_unit_for_byte_size(available),
57-
byte_size_in_proper_unit(threshold_available), proper_unit_for_byte_size(threshold_available));
54+
log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")",
55+
PROPERFMTARGS(available), PROPERFMTARGS(threshold_available));
5856
accept_trigger();
5957
return true;
6058
}

src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,29 @@ void ShenandoahFreeSet::log_status_under_lock() {
29212921
}
29222922
}
29232923

2924+
void ShenandoahFreeSet::log_freeset_stats(ShenandoahFreeSetPartitionId partition_id, LogStream& ls) {
2925+
size_t max = 0;
2926+
size_t total_free = 0;
2927+
size_t total_used = 0;
2928+
2929+
for (idx_t idx = _partitions.leftmost(partition_id);
2930+
idx <= _partitions.rightmost(partition_id); idx++) {
2931+
if (_partitions.in_free_set(partition_id, idx)) {
2932+
ShenandoahHeapRegion *r = _heap->get_region(idx);
2933+
size_t free = alloc_capacity(r);
2934+
max = MAX2(max, free);
2935+
total_free += free;
2936+
total_used += r->used();
2937+
}
2938+
}
2939+
2940+
ls.print(" %s freeset stats: Partition count: %zu, Reserved: " PROPERFMT ", Max free available in a single region: " PROPERFMT ";",
2941+
partition_name(partition_id),
2942+
_partitions.count(partition_id),
2943+
PROPERFMTARGS(total_free), PROPERFMTARGS(max)
2944+
);
2945+
}
2946+
29242947
void ShenandoahFreeSet::log_status() {
29252948
shenandoah_assert_heaplocked();
29262949

@@ -3040,20 +3063,18 @@ void ShenandoahFreeSet::log_status() {
30403063
// retired, the sum of used and capacities within regions that are still in the Mutator free partition may not match
30413064
// my internally tracked values of used() and free().
30423065
assert(free == total_free, "Free memory (%zu) should match calculated memory (%zu)", free, total_free);
3043-
ls.print("Free: %zu%s, Max: %zu%s regular, %zu%s humongous, ",
3044-
byte_size_in_proper_unit(total_free), proper_unit_for_byte_size(total_free),
3045-
byte_size_in_proper_unit(max), proper_unit_for_byte_size(max),
3046-
byte_size_in_proper_unit(max_humongous), proper_unit_for_byte_size(max_humongous)
3047-
);
3066+
ls.print("Whole heap stats: Total free: " PROPERFMT ", Total used: " PROPERFMT ", Max free in a single region: " PROPERFMT
3067+
", Max humongous: " PROPERFMT "; ",
3068+
PROPERFMTARGS(total_free), PROPERFMTARGS(total_used), PROPERFMTARGS(max), PROPERFMTARGS(max_humongous));
30483069

3049-
ls.print("Frag: ");
3070+
ls.print("Frag stats: ");
30503071
size_t frag_ext;
30513072
if (total_free_ext > 0) {
30523073
frag_ext = 100 - (100 * max_humongous / total_free_ext);
30533074
} else {
30543075
frag_ext = 0;
30553076
}
3056-
ls.print("%zu%% external, ", frag_ext);
3077+
ls.print("External: %zu%%, ", frag_ext);
30573078

30583079
size_t frag_int;
30593080
if (_partitions.count(ShenandoahFreeSetPartitionId::Mutator) > 0) {
@@ -3062,52 +3083,13 @@ void ShenandoahFreeSet::log_status() {
30623083
} else {
30633084
frag_int = 0;
30643085
}
3065-
ls.print("%zu%% internal; ", frag_int);
3066-
ls.print("Used: %zu%s, Mutator Free: %zu",
3067-
byte_size_in_proper_unit(total_used), proper_unit_for_byte_size(total_used),
3068-
_partitions.count(ShenandoahFreeSetPartitionId::Mutator));
3069-
}
3070-
3071-
{
3072-
size_t max = 0;
3073-
size_t total_free = 0;
3074-
size_t total_used = 0;
3075-
3076-
for (idx_t idx = _partitions.leftmost(ShenandoahFreeSetPartitionId::Collector);
3077-
idx <= _partitions.rightmost(ShenandoahFreeSetPartitionId::Collector); idx++) {
3078-
if (_partitions.in_free_set(ShenandoahFreeSetPartitionId::Collector, idx)) {
3079-
ShenandoahHeapRegion *r = _heap->get_region(idx);
3080-
size_t free = alloc_capacity(r);
3081-
max = MAX2(max, free);
3082-
total_free += free;
3083-
total_used += r->used();
3084-
}
3085-
}
3086-
ls.print(" Collector Reserve: %zu%s, Max: %zu%s; Used: %zu%s",
3087-
byte_size_in_proper_unit(total_free), proper_unit_for_byte_size(total_free),
3088-
byte_size_in_proper_unit(max), proper_unit_for_byte_size(max),
3089-
byte_size_in_proper_unit(total_used), proper_unit_for_byte_size(total_used));
3086+
ls.print("Internal: %zu%%; ", frag_int);
30903087
}
30913088

3089+
log_freeset_stats(ShenandoahFreeSetPartitionId::Mutator, ls);
3090+
log_freeset_stats(ShenandoahFreeSetPartitionId::Collector, ls);
30923091
if (_heap->mode()->is_generational()) {
3093-
size_t max = 0;
3094-
size_t total_free = 0;
3095-
size_t total_used = 0;
3096-
3097-
for (idx_t idx = _partitions.leftmost(ShenandoahFreeSetPartitionId::OldCollector);
3098-
idx <= _partitions.rightmost(ShenandoahFreeSetPartitionId::OldCollector); idx++) {
3099-
if (_partitions.in_free_set(ShenandoahFreeSetPartitionId::OldCollector, idx)) {
3100-
ShenandoahHeapRegion *r = _heap->get_region(idx);
3101-
size_t free = alloc_capacity(r);
3102-
max = MAX2(max, free);
3103-
total_free += free;
3104-
total_used += r->used();
3105-
}
3106-
}
3107-
ls.print_cr(" Old Collector Reserve: %zu%s, Max: %zu%s; Used: %zu%s",
3108-
byte_size_in_proper_unit(total_free), proper_unit_for_byte_size(total_free),
3109-
byte_size_in_proper_unit(max), proper_unit_for_byte_size(max),
3110-
byte_size_in_proper_unit(total_used), proper_unit_for_byte_size(total_used));
3092+
log_freeset_stats(ShenandoahFreeSetPartitionId::OldCollector, ls);
31113093
}
31123094
}
31133095
}

src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ using idx_t = ShenandoahSimpleBitMap::idx_t;
629629
void establish_old_collector_alloc_bias();
630630
size_t get_usable_free_words(size_t free_bytes) const;
631631

632+
void log_freeset_stats(ShenandoahFreeSetPartitionId partition_id, LogStream& ls);
632633
// log status, assuming lock has already been acquired by the caller.
633634
void log_status();
634635

src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -938,8 +938,8 @@ size_t ShenandoahGeneration::available_with_reserve() const {
938938
return result;
939939
}
940940

941-
size_t ShenandoahGeneration::soft_available() const {
942-
size_t result = available(ShenandoahHeap::heap()->soft_max_capacity());
941+
size_t ShenandoahGeneration::soft_mutator_available() const {
942+
size_t result = available(ShenandoahHeap::heap()->soft_max_capacity() * (100.0 - ShenandoahEvacReserve) / 100);
943943
return result;
944944
}
945945

src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class ShenandoahGeneration : public CHeapObj<mtGC>, public ShenandoahSpaceInfo {
126126
// The soft max heap size may be adjusted lower than the max heap size to cause the trigger
127127
// to believe it has less memory available than is _really_ available. Lowering the soft
128128
// max heap size will cause the adaptive heuristic to run more frequent cycles.
129-
size_t soft_available() const override;
129+
size_t soft_mutator_available() const override;
130130

131131
void log_status(const char* msg) const;
132132

src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,6 @@ size_t ShenandoahGlobalGeneration::available() const {
7878
return MIN2(available, ShenandoahHeap::heap()->free_set()->available());
7979
}
8080

81-
size_t ShenandoahGlobalGeneration::soft_available() const {
82-
size_t available = this->available();
83-
84-
// Make sure the code below treats available without the soft tail.
85-
assert(max_capacity() >= ShenandoahHeap::heap()->soft_max_capacity(), "Max capacity must be greater than soft max capacity.");
86-
size_t soft_tail = max_capacity() - ShenandoahHeap::heap()->soft_max_capacity();
87-
return (available > soft_tail) ? (available - soft_tail) : 0;
88-
}
89-
9081
void ShenandoahGlobalGeneration::set_concurrent_mark_in_progress(bool in_progress) {
9182
ShenandoahHeap* heap = ShenandoahHeap::heap();
9283
if (in_progress && heap->mode()->is_generational()) {

src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ class ShenandoahGlobalGeneration : public ShenandoahGeneration {
5656
size_t max_capacity() const override;
5757

5858
size_t available() const override;
59-
size_t soft_available() const override;
6059

6160
void set_concurrent_mark_in_progress(bool in_progress) override;
6261

0 commit comments

Comments
 (0)