Skip to content

Commit aa95215

Browse files
author
William Kemper
committed
8348595: GenShen: Fix generational free-memory no-progress check
Backport-of: ba6c965
1 parent 520667a commit aa95215

File tree

5 files changed

+27
-6
lines changed

5 files changed

+27
-6
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ void ShenandoahDegenGC::op_degenerated() {
305305

306306
// Check for futility and fail. There is no reason to do several back-to-back Degenerated cycles,
307307
// because that probably means the heap is overloaded and/or fragmented.
308-
if (!metrics.is_good_progress()) {
308+
if (!metrics.is_good_progress(_generation)) {
309309
heap->cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc);
310310
op_degenerated_futile();
311311
} else {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,9 @@ class ShenandoahFreeSet : public CHeapObj<mtGC> {
437437
// Acquire heap lock and log status, assuming heap lock is not acquired by the caller.
438438
void log_status_under_lock();
439439

440+
// Note that capacity is the number of regions that had available memory at most recent rebuild. It is not the
441+
// entire size of the young or global generation. (Regions within the generation that were fully utilized at time of
442+
// rebuild are not counted as part of capacity.)
440443
inline size_t capacity() const { return _partitions.capacity_of(ShenandoahFreeSetPartitionId::Mutator); }
441444
inline size_t used() const { return _partitions.used_by(ShenandoahFreeSetPartitionId::Mutator); }
442445

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void ShenandoahFullGC::op_full(GCCause::Cause cause) {
118118

119119
metrics.snap_after();
120120

121-
if (metrics.is_good_progress()) {
121+
if (metrics.is_good_progress(heap->global_generation())) {
122122
heap->notify_gc_progress();
123123
} else {
124124
// Nothing to do. Tell the allocation path that we have failed to make

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,28 @@ void ShenandoahMetricsSnapshot::snap_after() {
4343
_ef_after = _heap->free_set()->external_fragmentation();
4444
}
4545

46-
bool ShenandoahMetricsSnapshot::is_good_progress() {
46+
// For degenerated GC, generation is Young in generational mode, Global in non-generational mode.
47+
// For full GC, generation is always Global.
48+
//
49+
// Note that the size of the chosen collection set is proportional to the relevant generation's collection set.
50+
// Note also that the generation size may change following selection of the collection set, as a side effect
51+
// of evacuation. Evacuation may promote objects, causing old to grow and young to shrink. Or this may be a
52+
// mixed evacuation. When old regions are evacuated, this typically allows young to expand. In all of these
53+
// various scenarios, the purpose of asking is_good_progress() is to determine if there is enough memory available
54+
// within young generation to justify making an attempt to perform a concurrent collection. For this reason, we'll
55+
// use the current size of the generation (which may not be different than when the collection set was chosen) to
56+
// assess how much free memory we require in order to consider the most recent GC to have had good progress.
57+
58+
bool ShenandoahMetricsSnapshot::is_good_progress(ShenandoahGeneration* generation) {
4759
// Under the critical threshold?
48-
size_t free_actual = _heap->free_set()->available();
49-
size_t free_expected = _heap->max_capacity() / 100 * ShenandoahCriticalFreeThreshold;
60+
ShenandoahFreeSet* free_set = _heap->free_set();
61+
size_t free_actual = free_set->available();
62+
63+
// ShenandoahCriticalFreeThreshold is expressed as a percentage. We multiple this percentage by 1/100th
64+
// of the generation capacity to determine whether the available memory within the generation exceeds the
65+
// critical threshold.
66+
size_t free_expected = (generation->max_capacity() / 100) * ShenandoahCriticalFreeThreshold;
67+
5068
bool prog_free = free_actual >= free_expected;
5169
log_info(gc, ergo)("%s progress for free space: " SIZE_FORMAT "%s, need " SIZE_FORMAT "%s",
5270
prog_free ? "Good" : "Bad",

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ShenandoahMetricsSnapshot : public StackObj {
4040
void snap_before();
4141
void snap_after();
4242

43-
bool is_good_progress();
43+
bool is_good_progress(ShenandoahGeneration *generation);
4444
};
4545

4646
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHMETRICS_HPP

0 commit comments

Comments
 (0)