OpenJDK / jdk / jdk
changeset 54478:cdc54443fee5
8222186: Shenandoah should not uncommit below minimum heap size
Reviewed-by: zgu, rkennke
author | shade |
---|---|
date | Tue, 09 Apr 2019 21:20:16 +0200 |
parents | 511be32f3863 |
children | 6ad0281a654e |
files | src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp test/hotspot/jtreg/gc/shenandoah/mxbeans/TestMemoryMXBeans.java |
diffstat | 5 files changed, 54 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Tue Apr 09 21:20:15 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Tue Apr 09 21:20:16 2019 +0200 @@ -139,6 +139,11 @@ FLAG_SET_DEFAULT(ShenandoahUncommit, false); } + if ((InitialHeapSize == MaxHeapSize) && ShenandoahUncommit) { + log_info(gc)("Min heap equals to max heap, disabling ShenandoahUncommit"); + FLAG_SET_DEFAULT(ShenandoahUncommit, false); + } + // If class unloading is disabled, no unloading for concurrent cycles as well. // If class unloading is enabled, users should opt-in for unloading during // concurrent cycles.
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp Tue Apr 09 21:20:15 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp Tue Apr 09 21:20:16 2019 +0200 @@ -462,9 +462,11 @@ void ShenandoahControlThread::service_uncommit(double shrink_before) { ShenandoahHeap* heap = ShenandoahHeap::heap(); - // Scan through the heap and 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. + // 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; bool has_work = false; for (size_t i = 0; i < heap->num_regions(); i++) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Tue Apr 09 21:20:15 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Tue Apr 09 21:20:16 2019 +0200 @@ -141,6 +141,7 @@ // size_t init_byte_size = collector_policy()->initial_heap_byte_size(); + size_t min_byte_size = collector_policy()->min_heap_byte_size(); size_t max_byte_size = collector_policy()->max_heap_byte_size(); size_t heap_alignment = collector_policy()->heap_alignment(); @@ -159,8 +160,13 @@ size_t num_committed_regions = init_byte_size / reg_size_bytes; num_committed_regions = MIN2(num_committed_regions, _num_regions); assert(num_committed_regions <= _num_regions, "sanity"); - _initial_size = num_committed_regions * reg_size_bytes; + + size_t num_min_regions = min_byte_size / reg_size_bytes; + num_min_regions = MIN2(num_min_regions, _num_regions); + assert(num_min_regions <= _num_regions, "sanity"); + _minimum_size = num_min_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(); @@ -351,8 +357,11 @@ _control_thread = new ShenandoahControlThread(); - log_info(gc, init)("Initialize Shenandoah heap with initial size " SIZE_FORMAT "%s", - byte_size_in_proper_unit(_initial_size), proper_unit_for_byte_size(_initial_size)); + log_info(gc, init)("Initialize Shenandoah heap: " SIZE_FORMAT "%s initial, " SIZE_FORMAT "%s min, " SIZE_FORMAT "%s max", + byte_size_in_proper_unit(_initial_size), proper_unit_for_byte_size(_initial_size), + byte_size_in_proper_unit(_minimum_size), proper_unit_for_byte_size(_minimum_size), + byte_size_in_proper_unit(max_capacity()), proper_unit_for_byte_size(max_capacity()) + ); log_info(gc, init)("Safepointing mechanism: %s", SafepointMechanism::uses_thread_local_poll() ? "thread-local poll" : @@ -622,6 +631,10 @@ return _num_regions * ShenandoahHeapRegion::region_size_bytes(); } +size_t ShenandoahHeap::min_capacity() const { + return _minimum_size; +} + size_t ShenandoahHeap::initial_capacity() const { return _initial_size; } @@ -635,12 +648,22 @@ void ShenandoahHeap::op_uncommit(double shrink_before) { assert (ShenandoahUncommit, "should be enabled"); + // Application allocates from the beginning of the heap, and GC allocates at + // the end of it. It is more efficient to uncommit from the end, so that applications + // could enjoy the near committed regions. GC allocations are much less frequent, + // and therefore can accept the committing costs. + size_t count = 0; - for (size_t i = 0; i < num_regions(); i++) { - ShenandoahHeapRegion* r = get_region(i); + for (size_t i = num_regions(); i > 0; i--) { // care about size_t underflow + ShenandoahHeapRegion* r = get_region(i - 1); 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()) { + break; + } + r->make_uncommitted(); count++; }
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Tue Apr 09 21:20:15 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Tue Apr 09 21:20:16 2019 +0200 @@ -198,6 +198,7 @@ // private: size_t _initial_size; + size_t _minimum_size; DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t)); volatile size_t _used; volatile size_t _committed; @@ -216,6 +217,7 @@ size_t bytes_allocated_since_gc_start(); void reset_bytes_allocated_since_gc_start(); + size_t min_capacity() const; size_t max_capacity() const; size_t initial_capacity() const; size_t capacity() const;
--- a/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestMemoryMXBeans.java Tue Apr 09 21:20:15 2019 +0200 +++ b/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestMemoryMXBeans.java Tue Apr 09 21:20:16 2019 +0200 @@ -31,6 +31,8 @@ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g TestMemoryMXBeans -1 1024 * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms1g -Xmx1g TestMemoryMXBeans 1024 1024 * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms128m -Xmx1g TestMemoryMXBeans 128 1024 + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms1g -Xmx1g -XX:ShenandoahUncommitDelay=0 TestMemoryMXBeans 1024 1024 + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xms128m -Xmx1g -XX:ShenandoahUncommitDelay=0 TestMemoryMXBeans 128 1024 */ import java.lang.management.*; @@ -46,6 +48,9 @@ long initSize = 1L * Integer.parseInt(args[0]) * 1024 * 1024; long maxSize = 1L * Integer.parseInt(args[1]) * 1024 * 1024; + // wait for GC to uncommit + Thread.sleep(1000); + testMemoryBean(initSize, maxSize); } @@ -65,7 +70,15 @@ throw new IllegalStateException("Max heap size is wrong: " + heapMax + " vs " + maxSize); } if (initSize > 0 && maxSize > 0 && initSize != maxSize && heapCommitted == heapMax) { - throw new IllegalStateException("Init committed heap size is wrong: " + heapCommitted + + throw new IllegalStateException("Committed heap size is max: " + heapCommitted + + " (init: " + initSize + ", max: " + maxSize + ")"); + } + if (initSize > 0 && maxSize > 0 && initSize == maxSize && heapCommitted != heapMax) { + throw new IllegalStateException("Committed heap size is not max: " + heapCommitted + + " (init: " + initSize + ", max: " + maxSize + ")"); + } + if (initSize > 0 && heapCommitted < initSize) { + throw new IllegalStateException("Committed heap size is below min: " + heapCommitted + " (init: " + initSize + ", max: " + maxSize + ")"); } }