mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
8252660: Shenandoah: support manageable SoftMaxHeapSize option
Reviewed-by: zgu
This commit is contained in:
parent
261eb76ea2
commit
c61204b3f3
11 changed files with 314 additions and 33 deletions
|
@ -60,7 +60,7 @@ void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(Shenand
|
|||
// we hit max_cset. When max_cset is hit, we terminate the cset selection. Note that in this scheme,
|
||||
// ShenandoahGarbageThreshold is the soft threshold which would be ignored until min_garbage is hit.
|
||||
|
||||
size_t capacity = ShenandoahHeap::heap()->max_capacity();
|
||||
size_t capacity = ShenandoahHeap::heap()->soft_max_capacity();
|
||||
size_t max_cset = (size_t)((1.0 * capacity / 100 * ShenandoahEvacReserve) / ShenandoahEvacWaste);
|
||||
size_t free_target = (capacity / 100 * ShenandoahMinFreeThreshold) + max_cset;
|
||||
size_t min_garbage = (free_target > actual_free ? (free_target - actual_free) : 0);
|
||||
|
@ -102,9 +102,14 @@ void ShenandoahAdaptiveHeuristics::record_cycle_start() {
|
|||
|
||||
bool ShenandoahAdaptiveHeuristics::should_start_gc() const {
|
||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||
size_t capacity = heap->max_capacity();
|
||||
size_t max_capacity = heap->max_capacity();
|
||||
size_t capacity = heap->soft_max_capacity();
|
||||
size_t available = heap->free_set()->available();
|
||||
|
||||
// Make sure the code below treats available without the soft tail.
|
||||
size_t soft_tail = max_capacity - capacity;
|
||||
available = (available > soft_tail) ? (available - soft_tail) : 0;
|
||||
|
||||
// Check if we are falling below the worst limit, time to trigger the GC, regardless of
|
||||
// anything else.
|
||||
size_t min_threshold = capacity / 100 * ShenandoahMinFreeThreshold;
|
||||
|
|
|
@ -47,9 +47,14 @@ ShenandoahCompactHeuristics::ShenandoahCompactHeuristics() : ShenandoahHeuristic
|
|||
bool ShenandoahCompactHeuristics::should_start_gc() const {
|
||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||
|
||||
size_t capacity = heap->max_capacity();
|
||||
size_t max_capacity = heap->max_capacity();
|
||||
size_t capacity = heap->soft_max_capacity();
|
||||
size_t available = heap->free_set()->available();
|
||||
|
||||
// Make sure the code below treats available without the soft tail.
|
||||
size_t soft_tail = max_capacity - capacity;
|
||||
available = (available > soft_tail) ? (available - soft_tail) : 0;
|
||||
|
||||
size_t threshold_bytes_allocated = capacity / 100 * ShenandoahAllocationThreshold;
|
||||
size_t min_threshold = capacity / 100 * ShenandoahMinFreeThreshold;
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ void ShenandoahPassiveHeuristics::choose_collection_set_from_regiondata(Shenando
|
|||
|
||||
// Do not select too large CSet that would overflow the available free space.
|
||||
// Take at least the entire evacuation reserve, and be free to overflow to free space.
|
||||
size_t capacity = ShenandoahHeap::heap()->max_capacity();
|
||||
size_t available = MAX2(capacity / 100 * ShenandoahEvacReserve, actual_free);
|
||||
size_t max_capacity = ShenandoahHeap::heap()->max_capacity();
|
||||
size_t available = MAX2(max_capacity / 100 * ShenandoahEvacReserve, actual_free);
|
||||
size_t max_cset = (size_t)(available / ShenandoahEvacWaste);
|
||||
|
||||
log_info(gc, ergo)("CSet Selection. Actual Free: " SIZE_FORMAT "%s, Max CSet: " SIZE_FORMAT "%s",
|
||||
|
|
|
@ -42,8 +42,14 @@ ShenandoahStaticHeuristics::~ShenandoahStaticHeuristics() {}
|
|||
bool ShenandoahStaticHeuristics::should_start_gc() const {
|
||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||
|
||||
size_t capacity = heap->max_capacity();
|
||||
size_t max_capacity = heap->max_capacity();
|
||||
size_t capacity = heap->soft_max_capacity();
|
||||
size_t available = heap->free_set()->available();
|
||||
|
||||
// Make sure the code below treats available without the soft tail.
|
||||
size_t soft_tail = max_capacity - capacity;
|
||||
available = (available > soft_tail) ? (available - soft_tail) : 0;
|
||||
|
||||
size_t threshold_available = capacity / 100 * ShenandoahMinFreeThreshold;
|
||||
|
||||
if (available < threshold_available) {
|
||||
|
|
|
@ -103,6 +103,9 @@ void ShenandoahControlThread::run_service() {
|
|||
// This control loop iteration have seen this much allocations.
|
||||
size_t allocs_seen = Atomic::xchg(&_allocs_seen, (size_t)0);
|
||||
|
||||
// Check if we have seen a new target for soft max heap size.
|
||||
bool soft_max_changed = check_soft_max_changed();
|
||||
|
||||
// Choose which GC mode to run in. The block below should select a single mode.
|
||||
GCMode mode = none;
|
||||
GCCause::Cause cause = GCCause::_last_gc_cause;
|
||||
|
@ -291,13 +294,20 @@ void ShenandoahControlThread::run_service() {
|
|||
|
||||
double current = os::elapsedTime();
|
||||
|
||||
if (ShenandoahUncommit && (explicit_gc_requested || (current - last_shrink_time > shrink_period))) {
|
||||
// Try to uncommit enough stale regions. Explicit GC tries to uncommit everything.
|
||||
// Regular paths uncommit only occasionally.
|
||||
double shrink_before = explicit_gc_requested ?
|
||||
if (ShenandoahUncommit && (explicit_gc_requested || soft_max_changed || (current - last_shrink_time > shrink_period))) {
|
||||
// Explicit GC tries to uncommit everything down to min capacity.
|
||||
// Soft max change tries to uncommit everything down to target capacity.
|
||||
// Periodic uncommit tries to uncommit suitable regions down to min capacity.
|
||||
|
||||
double shrink_before = (explicit_gc_requested || soft_max_changed) ?
|
||||
current :
|
||||
current - (ShenandoahUncommitDelay / 1000.0);
|
||||
service_uncommit(shrink_before);
|
||||
|
||||
size_t shrink_until = soft_max_changed ?
|
||||
heap->soft_max_capacity() :
|
||||
heap->min_capacity();
|
||||
|
||||
service_uncommit(shrink_before, shrink_until);
|
||||
heap->phase_timings()->flush_cycle_to_global();
|
||||
last_shrink_time = current;
|
||||
}
|
||||
|
@ -320,6 +330,25 @@ void ShenandoahControlThread::run_service() {
|
|||
}
|
||||
}
|
||||
|
||||
bool ShenandoahControlThread::check_soft_max_changed() const {
|
||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||
size_t new_soft_max = Atomic::load(&SoftMaxHeapSize);
|
||||
size_t old_soft_max = heap->soft_max_capacity();
|
||||
if (new_soft_max != old_soft_max) {
|
||||
new_soft_max = MAX2(heap->min_capacity(), new_soft_max);
|
||||
new_soft_max = MIN2(heap->max_capacity(), new_soft_max);
|
||||
if (new_soft_max != old_soft_max) {
|
||||
log_info(gc)("Soft Max Heap Size: " SIZE_FORMAT "%s -> " SIZE_FORMAT "%s",
|
||||
byte_size_in_proper_unit(old_soft_max), proper_unit_for_byte_size(old_soft_max),
|
||||
byte_size_in_proper_unit(new_soft_max), proper_unit_for_byte_size(new_soft_max)
|
||||
);
|
||||
heap->set_soft_max_capacity(new_soft_max);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cause) {
|
||||
// Normal cycle goes via all concurrent phases. If allocation failure (af) happens during
|
||||
// any of the concurrent phases, it first degrades to Degenerated GC and completes GC there.
|
||||
|
@ -479,14 +508,14 @@ void ShenandoahControlThread::service_stw_degenerated_cycle(GCCause::Cause cause
|
|||
heap->shenandoah_policy()->record_success_degenerated();
|
||||
}
|
||||
|
||||
void ShenandoahControlThread::service_uncommit(double shrink_before) {
|
||||
void ShenandoahControlThread::service_uncommit(double shrink_before, size_t shrink_until) {
|
||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||
|
||||
// Determine if there is work to do. This avoids taking heap lock if there is
|
||||
// no work available, avoids spamming logs with superfluous logging messages,
|
||||
// and minimises the amount of work while locks are taken.
|
||||
|
||||
if (heap->committed() <= heap->min_capacity()) return;
|
||||
if (heap->committed() <= shrink_until) return;
|
||||
|
||||
bool has_work = false;
|
||||
for (size_t i = 0; i < heap->num_regions(); i++) {
|
||||
|
@ -498,7 +527,7 @@ void ShenandoahControlThread::service_uncommit(double shrink_before) {
|
|||
}
|
||||
|
||||
if (has_work) {
|
||||
heap->entry_uncommit(shrink_before);
|
||||
heap->entry_uncommit(shrink_before, shrink_until);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ private:
|
|||
void service_concurrent_normal_cycle(GCCause::Cause cause);
|
||||
void service_stw_full_cycle(GCCause::Cause cause);
|
||||
void service_stw_degenerated_cycle(GCCause::Cause cause, ShenandoahHeap::ShenandoahDegenPoint point);
|
||||
void service_uncommit(double shrink_before);
|
||||
void service_uncommit(double shrink_before, size_t shrink_until);
|
||||
|
||||
bool try_set_alloc_failure_gc();
|
||||
void notify_alloc_failure_waiters();
|
||||
|
@ -120,6 +120,9 @@ private:
|
|||
void handle_requested_gc(GCCause::Cause cause);
|
||||
|
||||
bool is_explicit_gc(GCCause::Cause cause) const;
|
||||
|
||||
bool check_soft_max_changed() const;
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
ShenandoahControlThread();
|
||||
|
|
|
@ -163,6 +163,9 @@ jint ShenandoahHeap::initialize() {
|
|||
assert(num_min_regions <= _num_regions, "sanity");
|
||||
_minimum_size = num_min_regions * reg_size_bytes;
|
||||
|
||||
// Default to max heap size.
|
||||
_soft_max_size = _num_regions * reg_size_bytes;
|
||||
|
||||
_committed = _initial_size;
|
||||
|
||||
size_t heap_page_size = UseLargePages ? (size_t)os::large_page_size() : (size_t)os::vm_page_size();
|
||||
|
@ -538,8 +541,9 @@ void ShenandoahHeap::reset_mark_bitmap() {
|
|||
|
||||
void ShenandoahHeap::print_on(outputStream* st) const {
|
||||
st->print_cr("Shenandoah Heap");
|
||||
st->print_cr(" " SIZE_FORMAT "%s total, " SIZE_FORMAT "%s committed, " SIZE_FORMAT "%s used",
|
||||
st->print_cr(" " SIZE_FORMAT "%s max, " SIZE_FORMAT "%s soft max, " SIZE_FORMAT "%s committed, " SIZE_FORMAT "%s used",
|
||||
byte_size_in_proper_unit(max_capacity()), proper_unit_for_byte_size(max_capacity()),
|
||||
byte_size_in_proper_unit(soft_max_capacity()), proper_unit_for_byte_size(soft_max_capacity()),
|
||||
byte_size_in_proper_unit(committed()), proper_unit_for_byte_size(committed()),
|
||||
byte_size_in_proper_unit(used()), proper_unit_for_byte_size(used()));
|
||||
st->print_cr(" " SIZE_FORMAT " x " SIZE_FORMAT"%s regions",
|
||||
|
@ -676,6 +680,21 @@ size_t ShenandoahHeap::max_capacity() const {
|
|||
return _num_regions * ShenandoahHeapRegion::region_size_bytes();
|
||||
}
|
||||
|
||||
size_t ShenandoahHeap::soft_max_capacity() const {
|
||||
size_t v = Atomic::load(&_soft_max_size);
|
||||
assert(min_capacity() <= v && v <= max_capacity(),
|
||||
"Should be in bounds: " SIZE_FORMAT " <= " SIZE_FORMAT " <= " SIZE_FORMAT,
|
||||
min_capacity(), v, max_capacity());
|
||||
return v;
|
||||
}
|
||||
|
||||
void ShenandoahHeap::set_soft_max_capacity(size_t v) {
|
||||
assert(min_capacity() <= v && v <= max_capacity(),
|
||||
"Should be in bounds: " SIZE_FORMAT " <= " SIZE_FORMAT " <= " SIZE_FORMAT,
|
||||
min_capacity(), v, max_capacity());
|
||||
Atomic::store(&_soft_max_size, v);
|
||||
}
|
||||
|
||||
size_t ShenandoahHeap::min_capacity() const {
|
||||
return _minimum_size;
|
||||
}
|
||||
|
@ -690,7 +709,7 @@ bool ShenandoahHeap::is_in(const void* p) const {
|
|||
return p >= heap_base && p < last_region_end;
|
||||
}
|
||||
|
||||
void ShenandoahHeap::op_uncommit(double shrink_before) {
|
||||
void ShenandoahHeap::op_uncommit(double shrink_before, size_t shrink_until) {
|
||||
assert (ShenandoahUncommit, "should be enabled");
|
||||
|
||||
// Application allocates from the beginning of the heap, and GC allocates at
|
||||
|
@ -704,8 +723,7 @@ void ShenandoahHeap::op_uncommit(double shrink_before) {
|
|||
if (r->is_empty_committed() && (r->empty_time() < shrink_before)) {
|
||||
ShenandoahHeapLocker locker(lock());
|
||||
if (r->is_empty_committed()) {
|
||||
// Do not uncommit below minimal capacity
|
||||
if (committed() < min_capacity() + ShenandoahHeapRegion::region_size_bytes()) {
|
||||
if (committed() < shrink_until + ShenandoahHeapRegion::region_size_bytes()) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2960,12 +2978,12 @@ void ShenandoahHeap::entry_preclean() {
|
|||
}
|
||||
}
|
||||
|
||||
void ShenandoahHeap::entry_uncommit(double shrink_before) {
|
||||
void ShenandoahHeap::entry_uncommit(double shrink_before, size_t shrink_until) {
|
||||
static const char *msg = "Concurrent uncommit";
|
||||
ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_uncommit, true /* log_heap_usage */);
|
||||
EventMark em("%s", msg);
|
||||
|
||||
op_uncommit(shrink_before);
|
||||
op_uncommit(shrink_before, shrink_until);
|
||||
}
|
||||
|
||||
void ShenandoahHeap::try_inject_alloc_failure() {
|
||||
|
|
|
@ -158,6 +158,7 @@ public:
|
|||
private:
|
||||
size_t _initial_size;
|
||||
size_t _minimum_size;
|
||||
volatile size_t _soft_max_size;
|
||||
shenandoah_padding(0);
|
||||
volatile size_t _used;
|
||||
volatile size_t _committed;
|
||||
|
@ -178,11 +179,14 @@ public:
|
|||
|
||||
size_t min_capacity() const;
|
||||
size_t max_capacity() const;
|
||||
size_t soft_max_capacity() const;
|
||||
size_t initial_capacity() const;
|
||||
size_t capacity() const;
|
||||
size_t used() const;
|
||||
size_t committed() const;
|
||||
|
||||
void set_soft_max_capacity(size_t v);
|
||||
|
||||
// ---------- Workers handling
|
||||
//
|
||||
private:
|
||||
|
@ -390,7 +394,7 @@ public:
|
|||
void entry_evac();
|
||||
void entry_updaterefs();
|
||||
void entry_cleanup_complete();
|
||||
void entry_uncommit(double shrink_before);
|
||||
void entry_uncommit(double shrink_before, size_t shrink_until);
|
||||
|
||||
private:
|
||||
// Actual work for the phases
|
||||
|
@ -415,7 +419,7 @@ private:
|
|||
void op_stw_evac();
|
||||
void op_updaterefs();
|
||||
void op_cleanup_complete();
|
||||
void op_uncommit(double shrink_before);
|
||||
void op_uncommit(double shrink_before, size_t shrink_until);
|
||||
|
||||
void rendezvous_threads();
|
||||
|
||||
|
|
|
@ -106,26 +106,26 @@
|
|||
"How much heap should be free before some heuristics trigger the "\
|
||||
"initial (learning) cycles. Affects cycle frequency on startup " \
|
||||
"and after drastic state changes, e.g. after degenerated/full " \
|
||||
"GC cycles. In percents of total heap size.") \
|
||||
"GC cycles. In percents of (soft) max heap size.") \
|
||||
range(0,100) \
|
||||
\
|
||||
experimental(uintx, ShenandoahMinFreeThreshold, 10, \
|
||||
"How much heap should be free before most heuristics trigger the "\
|
||||
"collection, even without other triggers. Provides the safety " \
|
||||
"margin for many heuristics. In percents of total heap size.") \
|
||||
"margin for many heuristics. In percents of (soft) max heap size.")\
|
||||
range(0,100) \
|
||||
\
|
||||
experimental(uintx, ShenandoahAllocationThreshold, 0, \
|
||||
"How many new allocations should happen since the last GC cycle " \
|
||||
"before some heuristics trigger the collection. In percents of " \
|
||||
"total heap size. Set to zero to effectively disable.") \
|
||||
"(soft) max heap size. Set to zero to effectively disable.") \
|
||||
range(0,100) \
|
||||
\
|
||||
experimental(uintx, ShenandoahAllocSpikeFactor, 5, \
|
||||
"How much of heap should some heuristics reserve for absorbing " \
|
||||
"the allocation spikes. Larger value wastes more memory in " \
|
||||
"non-emergency cases, but provides more safety in emergency " \
|
||||
"cases. In percents of total heap size.") \
|
||||
"cases. In percents of (soft) max heap size.") \
|
||||
range(0,100) \
|
||||
\
|
||||
experimental(uintx, ShenandoahLearningSteps, 5, \
|
||||
|
|
137
test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java
Normal file
137
test/hotspot/jtreg/gc/shenandoah/TestDynamicSoftMaxHeapSize.java
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Red Hat, Inc. 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestDynamicSoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
|
||||
* -XX:+ShenandoahDegeneratedGC
|
||||
* -Dtarget=10000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
|
||||
* -XX:-ShenandoahDegeneratedGC
|
||||
* -Dtarget=10000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestDynamicSoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
|
||||
* -Dtarget=1000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestDynamicSoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
|
||||
* -Dtarget=10000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestDynamicSoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
|
||||
* -Dtarget=10000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestDynamicSoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
|
||||
* -Dtarget=1000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestDynamicSoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu -XX:ShenandoahGCHeuristics=aggressive
|
||||
* -Dtarget=1000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestDynamicSoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm -Xms16m -Xmx512m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
|
||||
* -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu
|
||||
* -Dtarget=10000
|
||||
* TestDynamicSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
import java.util.Random;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.dcmd.PidJcmdExecutor;
|
||||
|
||||
public class TestDynamicSoftMaxHeapSize {
|
||||
|
||||
static final long TARGET_MB = Long.getLong("target", 10_000); // 10 Gb allocation
|
||||
static final long STRIDE = 10_000_000;
|
||||
|
||||
static volatile Object sink;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
long count = TARGET_MB * 1024 * 1024 / 16;
|
||||
Random r = Utils.getRandomInstance();
|
||||
PidJcmdExecutor jcmd = new PidJcmdExecutor();
|
||||
|
||||
for (long c = 0; c < count; c += STRIDE) {
|
||||
// Sizes specifically include heaps below Xms and above Xmx to test saturation code.
|
||||
jcmd.execute("VM.set_flag SoftMaxHeapSize " + r.nextInt(768*1024*1024), true);
|
||||
for (long s = 0; s < STRIDE; s++) {
|
||||
sink = new Object();
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Red Hat, Inc. 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestSoftMaxHeapSize
|
||||
* @summary Test that Shenandoah checks SoftMaxHeapSize
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @run driver TestSoftMaxHeapSize
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class TestSoftMaxHeapSize {
|
||||
public static void main(String[] args) throws Exception {
|
||||
{
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+UseShenandoahGC",
|
||||
"-Xms4m",
|
||||
"-Xmx128m",
|
||||
"-XX:SoftMaxHeapSize=4m",
|
||||
"-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
{
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+UseShenandoahGC",
|
||||
"-Xms4m",
|
||||
"-Xmx128m",
|
||||
"-XX:SoftMaxHeapSize=128m",
|
||||
"-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
{
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+UseShenandoahGC",
|
||||
"-Xms4m",
|
||||
"-Xmx128m",
|
||||
"-XX:SoftMaxHeapSize=129m",
|
||||
"-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(1);
|
||||
output.shouldContain("SoftMaxHeapSize must be less than or equal to the maximum heap size");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue