diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp index 2d0bbfd5e4a..2361a50e76d 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp @@ -412,7 +412,7 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() { size_t defrag_count = 0; size_t total_uncollected_old_regions = _last_old_region - _last_old_collection_candidate; - if (cand_idx > _last_old_collection_candidate) { + if ((ShenandoahGenerationalHumongousReserve > 0) && (cand_idx > _last_old_collection_candidate)) { // Above, we have added into the set of mixed-evacuation candidates all old-gen regions for which the live memory // that they contain is below a particular old-garbage threshold. Regions that were not selected for the collection // set hold enough live memory that it is not considered efficient (by "garbage-first standards") to compact these diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index 25afcfcb10e..fafa3fde437 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -535,6 +535,8 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) { const size_t old_garbage_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahOldGarbageThreshold) / 100; + const size_t pip_used_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahGenerationalMinPIPUsage) / 100; + size_t old_consumed = 0; size_t promo_potential = 0; size_t candidates = 0; @@ -557,10 +559,8 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) { continue; } if (heap->is_tenurable(r)) { - if ((r->garbage() < old_garbage_threshold)) { - // This tenure-worthy region has too little garbage, so we do not want to expend the copying effort to - // reclaim the garbage; instead this region may be eligible for promotion-in-place to the - // old generation. + if ((r->garbage() < old_garbage_threshold) && (r->used() > pip_used_threshold)) { + // We prefer to promote this region in place because is has a small amount of garbage and a large usage. HeapWord* tams = ctx->top_at_mark_start(r); HeapWord* original_top = r->top(); if (!heap->is_concurrent_old_mark_in_progress() && tams == original_top) { @@ -586,7 +586,7 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) { // Else, we do not promote this region (either in place or by copy) because it has received new allocations. // During evacuation, we exclude from promotion regions for which age > tenure threshold, garbage < garbage-threshold, - // and get_top_before_promote() != tams + // used > pip_used_threshold, and get_top_before_promote() != tams } else { // Record this promotion-eligible candidate region. After sorting and selecting the best candidates below, // we may still decide to exclude this promotion-eligible region from the current collection set. If this diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp index 3a0d7926865..971129beea8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp @@ -146,7 +146,13 @@ void ShenandoahGenerationalEvacuationTask::maybe_promote_region(ShenandoahHeapRe // more garbage than ShenandoahOldGarbageThreshold, we'll promote by evacuation. If there is room for evacuation // in this cycle, the region will be in the collection set. If there is not room, the region will be promoted // by evacuation in some future GC cycle. - promote_humongous(r); + + // We do not promote primitive arrays because there's no performance penalty keeping them in young. When/if they + // become garbage, reclaiming the memory from young is much quicker and more efficient than reclaiming them from old. + oop obj = cast_to_oop(r->bottom()); + if (!obj->is_typeArray()) { + promote_humongous(r); + } } else if (r->is_regular() && (r->get_top_before_promote() != nullptr)) { // Likewise, we cannot put promote-in-place regions into the collection set because that would also trigger // the LRB to copy on reference fetch. diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index 1321baa6366..c6a842c7754 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -34,6 +34,20 @@ range, \ constraint) \ \ + product(uintx, ShenandoahGenerationalMinPIPUsage, 30, EXPERIMENTAL, \ + "(Generational mode only) What percent of a heap region " \ + "should be used before we consider promoting a region in " \ + "place? Regions with less than this amount of used will " \ + "promoted by evacuation. A benefit of promoting in place " \ + "is that less work is required by the GC at the time the " \ + "region is promoted. A disadvantage of promoting in place " \ + "is that this introduces fragmentation of old-gen memory, " \ + "with old-gen regions scattered throughout the heap. Regions " \ + "that have been promoted in place may need to be evacuated at " \ + "a later time in order to compact old-gen memory to enable " \ + "future humongous allocations.") \ + range(0,100) \ + \ product(uintx, ShenandoahGenerationalHumongousReserve, 0, EXPERIMENTAL, \ "(Generational mode only) What percent of the heap should be " \ "reserved for humongous objects if possible. Old-generation " \ @@ -165,7 +179,7 @@ "collector accepts. In percents of heap region size.") \ range(0,100) \ \ - product(uintx, ShenandoahOldGarbageThreshold, 15, EXPERIMENTAL, \ + product(uintx, ShenandoahOldGarbageThreshold, 25, EXPERIMENTAL, \ "How much garbage an old region has to contain before it would " \ "be taken for collection.") \ range(0,100) \