Skip to content

Commit

Permalink
FEAT(gc): Free physical memory backend by heap after FullGC or shrink…
Browse files Browse the repository at this point in the history
… operation

After FullGC or shrink, some continuous heap area are free and perhaps will not be uesed
in short time, so we can madvise the backup pyhsical memory for more java process

--story=855956801

Contributed-by:wattsun,bobpengxie
  • Loading branch information
wattsun110 authored and linzang committed Nov 6, 2020
1 parent 8d0f1d7 commit 4898f20
Show file tree
Hide file tree
Showing 29 changed files with 375 additions and 3 deletions.
3 changes: 3 additions & 0 deletions hotspot/src/os/aix/vm/os_aix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2232,6 +2232,9 @@ void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
}

//to be implemented
void os::pd_free_heap_physical_memory(char *addr, size_t bytes) {}

void os::numa_make_global(char *addr, size_t bytes) {
}

Expand Down
3 changes: 3 additions & 0 deletions hotspot/src/os/bsd/vm/os_bsd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2266,6 +2266,9 @@ void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
::madvise(addr, bytes, MADV_DONTNEED);
}

//to be implemented
void os::pd_free_heap_physical_memory(char *addr, size_t bytes) {}

void os::numa_make_global(char *addr, size_t bytes) {
}

Expand Down
4 changes: 4 additions & 0 deletions hotspot/src/os/linux/vm/os_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6485,6 +6485,10 @@ bool os::is_headless_jre() {
return true;
}

void os::pd_free_heap_physical_memory(char *addr, size_t bytes) {
::madvise(addr, bytes, MADV_DONTNEED);
}

// Get the default path to the core file
// Returns the length of the string
int os::get_core_path(char* buffer, size_t bufferSize) {
Expand Down
4 changes: 4 additions & 0 deletions hotspot/src/os/solaris/vm/os_solaris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2681,6 +2681,10 @@ void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) {
}
}

//to be implemented
void os::pd_free_heap_physical_memory(char *addr, size_t bytes) {
}

bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
return os::commit_memory(addr, size, !ExecMem);
}
Expand Down
1 change: 1 addition & 0 deletions hotspot/src/os/windows/vm/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3512,6 +3512,7 @@ bool os::unguard_memory(char* addr, size_t bytes) {

void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { }
void os::pd_free_heap_physical_memory(char *addr, size_t bytes) { }
void os::numa_make_global(char *addr, size_t bytes) { }
void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { }
bool os::numa_topology_changed() { return false; }
Expand Down
2 changes: 1 addition & 1 deletion hotspot/src/share/vm/classfile/classFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4220,7 +4220,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
if (PrintClassLoadingDetails) {
tty->date_stamp(true);
tty->print(" [Loaded %s from %s by classloader: %s (%p)]\n", this_klass->external_name(),
cfs->source(), (class_loader.is_null() ? "bootstrap" : InstanceKlass::cast(class_loader->klass())->external_name()), class_loader);
cfs->source(), (class_loader.is_null() ? "bootstrap" : InstanceKlass::cast(class_loader->klass())->external_name()), class_loader());
}else {
tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
cfs->source());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ void CompactibleFreeListSpace::reset(MemRegion mr) {
// Everything's allocated until proven otherwise.
_bt.set_unallocated_block(end());
}
if (FreeHeapPhysicalMemory) {
_gen->free_heap_physical_memory_after_fullgc(mr.start(), mr.end());
}

if (!mr.is_empty()) {
assert(mr.word_size() >= MinChunkSize, "Chunk size is too small");
_bt.single_block(mr.start(), mr.word_size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,12 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
// Grow generation to reserved size.
bool grow_to_reserved();

//free heap memory
void free_heap_physical_memory_after_fullgc(void* start, void* end) {
GenCollectedHeap* gch = GenCollectedHeap::heap();
gch->free_heap_physical_memory_after_fullgc(start, end);
}

void clear_expansion_cause() { _expansion_cause = CMSExpansionCause::_no_expansion; }

// Space enquiries
Expand Down
27 changes: 27 additions & 0 deletions hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,33 @@ void ConcurrentMark::completeCleanup() {
_cleanup_list.length());
}

if (FreeHeapPhysicalMemory) {
size_t free_heap_physical_memory_total_byte_size =0;
double start_sec = os::elapsedTime();
int tmp_free_list_length = 0;
int should_be_freed_region_length = 0;
int diff = 0;
//free regions physical memory
HeapRegion* cur = tmp_free_list.head();
//to calculate the first region in the middle of the tmp_free_list
diff = (int)(((100 - G1SecondaryFreeListFreeMemoryThresholdPercent) * tmp_free_list.length()) / 100) / 2;
//region num to be free physical memroy
should_be_freed_region_length =
tmp_free_list.length() * G1SecondaryFreeListFreeMemoryThresholdPercent / 100;
//forward cur to the right region
for (int i = 0; i < diff && cur != NULL; i++) {
cur = cur->next();
}

for (int i = 0; i < should_be_freed_region_length && cur != NULL; i++) {
free_heap_physical_memory_total_byte_size += cur->capacity();
os::free_heap_physical_memory(((char*)cur->bottom()), cur->capacity());
cur = cur->next();
}
double end_sec = os::elapsedTime();
g1h->add_heap_physical_memory_free_info(end_sec - start_sec, free_heap_physical_memory_total_byte_size, should_be_freed_region_length);
}

{
MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
g1h->secondary_free_list_add(&tmp_free_list);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,10 @@ void ConcurrentMarkThread::run() {
double cleanup_end_sec = os::elapsedTime();
if (G1Log::fine()) {
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]",
gclog_or_tty->print("[GC concurrent-cleanup-end, %1.7lf secs]",
cleanup_end_sec - cleanup_start_sec);
g1h->print_heap_physical_memory_free_info();
gclog_or_tty->cr();
}
}
guarantee(cm()->cleanup_list_is_empty(),
Expand Down
67 changes: 67 additions & 0 deletions hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,11 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
gc_epilogue(true);
}

if (FreeHeapPhysicalMemory) {
//should free heap memory
free_heap_physical_memory_after_fullgc();
}

if (G1Log::finer()) {
g1_policy()->print_detailed_heap_transition(true /* full */);
}
Expand All @@ -1538,6 +1543,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,

post_full_gc_dump(gc_timer);


gc_timer->register_gc_end();
gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions());
}
Expand Down Expand Up @@ -1786,6 +1792,47 @@ bool G1CollectedHeap::expand(size_t expand_bytes) {
return regions_to_expand > 0;
}

void G1CollectedHeap::free_heap_physical_memory_after_fullgc() {
double start_sec = os::elapsedTime();
int num_free_regions = _hrm.num_free_regions();
//max regions will be used by mutator and if used regions has exceeded
//this, will trigger expand or gc for free regions
int max_young_region_num = (int)_g1_policy->young_list_target_length();
int current_young_region_num = young_list()->length();
//after fullgc, young_ist may be empty mostly
int diff = max_young_region_num - current_young_region_num;
//how many regions will be used for old gen in the _free_list freed by FullGC
int old_heap_region_num = num_free_regions - diff;
if (old_heap_region_num <= 0) {
return;
}
FreeRegionList* free_list = _hrm.free_list();
int free_list_length = free_list->length();
int reclaim_region_count = (int)((free_list_length - diff) * G1FreeOldMemoryThresholdPercentAfterFullGC) / 100;

/* free_list is a double linked list sorted by region index, young generation will get regions from tail,
* while old gen get region from head, for performance, we skip the young region and free the second part
* of the old heap region
*/
HeapRegion* tail = free_list->tail();
//forward to the right region
for (int i = 0; i < diff && tail != NULL; i++) {
tail = tail->prev();
}
HeapRegion* cur = tail;

guarantee (cur != NULL, "Invariant") ;
for (int i = 0; i < reclaim_region_count && cur != NULL; i++) {
_free_heap_physical_memory_total_byte_size += cur->capacity();
os::free_heap_physical_memory(((char*)cur->bottom()), cur->capacity());
cur = cur->prev();
}
_reclaim_region_count = reclaim_region_count;
double end_sec = os::elapsedTime();
_free_heap_physical_memory_time_sec = end_sec - start_sec;
return;
}

void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
size_t aligned_shrink_bytes =
ReservedSpace::page_align_size_down(shrink_bytes);
Expand Down Expand Up @@ -7023,3 +7070,23 @@ void G1CollectedHeap::rebuild_strong_code_roots() {
RebuildStrongCodeRootClosure blob_cl(this);
CodeCache::blobs_do(&blob_cl);
}

void G1CollectedHeap::print_heap_physical_memory_free_info() {
if (PrintGCDetails) {
gclog_or_tty->print(", [free physical memory: " SIZE_FORMAT " KB, " SIZE_FORMAT " regions, %3.7f secs]",\
_free_heap_physical_memory_total_byte_size / K,_reclaim_region_count,
_free_heap_physical_memory_time_sec);
}
//reset
_free_heap_physical_memory_time_sec = 0;
_free_heap_physical_memory_total_byte_size = 0;
_reclaim_region_count = 0;
}


void G1CollectedHeap::add_heap_physical_memory_free_info(double free_heap_physical_memory_time_sec,
size_t free_heap_physical_memory_total_byte_size,int reclaim_region_count){
_free_heap_physical_memory_time_sec += free_heap_physical_memory_time_sec;
_free_heap_physical_memory_total_byte_size += free_heap_physical_memory_total_byte_size;
_reclaim_region_count += reclaim_region_count;
}
8 changes: 8 additions & 0 deletions hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ class G1CollectedHeap : public SharedHeap {
// It keeps track of the humongous regions.
HeapRegionSet _humongous_set;

int _reclaim_region_count;

void eagerly_reclaim_humongous_regions();

// The number of regions we could create by expansion.
Expand Down Expand Up @@ -648,6 +650,12 @@ class G1CollectedHeap : public SharedHeap {
// (Rounds up to a HeapRegion boundary.)
bool expand(size_t expand_bytes);

void free_heap_physical_memory_after_fullgc();
virtual void print_heap_physical_memory_free_info();
void add_heap_physical_memory_free_info(double free_heap_physical_memory_time_sec,
size_t free_heap_physical_memory_total_byte_size,
int reclaim_region_count);

// Returns the PLAB statistics for a given destination.
inline PLABStats* alloc_buffer_stats(InCSetState dest);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,9 @@ void G1CollectorPolicy::print_detailed_heap_transition(bool full) {

if (full) {
MetaspaceAux::print_metaspace_change(_metaspace_used_bytes_before_gc);
if (FreeHeapPhysicalMemory) {
G1CollectedHeap::heap()->print_heap_physical_memory_free_info();
}
}

gclog_or_tty->cr();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,11 @@ void G1PageBasedVirtualSpace::uncommit_internal(size_t start_page, size_t end_pa
err_msg("Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page));

char* start_addr = page_start(start_page);
os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char)));
bool res = os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char)));
//should madvise the physical memory only after uncommit operation succeed
if (res && FreeHeapPhysicalMemory) {
os::free_heap_physical_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char)));
}
}

void G1PageBasedVirtualSpace::uncommit(size_t start_page, size_t size_in_pages) {
Expand Down
8 changes: 8 additions & 0 deletions hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
"Target duration of individual concurrent marking steps " \
"in milliseconds.") \
\
product(double, G1FreeOldMemoryThresholdPercentAfterFullGC, 70, \
"Target percent to free old generation physical memory " \
"after FullGC.") \
\
product(intx, G1RefProcDrainInterval, 10, \
"The number of discovered reference objects to process before " \
"draining concurrent marking work queues.") \
Expand Down Expand Up @@ -232,6 +236,10 @@
"The number of regions we will add to the secondary free list " \
"at every append operation") \
\
product(double, G1SecondaryFreeListFreeMemoryThresholdPercent, 50, \
"Target percent of heap regions that will be recycled by" \
"concurrent gc.") \
\
develop(bool, G1ConcRegionFreeingVerbose, false, \
"Enables verboseness during concurrent region freeing") \
\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ class HeapRegionManager: public CHeapObj<mtGC> {
}
return hr;
}

FreeRegionList* free_list() {
return &_free_list;
}

inline void allocate_free_regions_starting_at(uint first, uint num_regions);

Expand Down
8 changes: 8 additions & 0 deletions hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ class FreeRegionList : public HeapRegionSetBase {

void verify_list();

HeapRegion* head() {
return _head;
}

HeapRegion* tail() {
return _tail;
}

#ifdef ASSERT
bool contains(HeapRegion* hr) const {
return hr->containing_set() == this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
#include "gc_implementation/parallelScavenge/psMarkSweepDecorator.hpp"
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {

// Let the size policy know we're done
size_policy->major_collection_end(old_gen->used_in_bytes(), gc_cause);
if (FreeHeapPhysicalMemory) {
void* start = old_gen->object_space()->top();
void* end = old_gen->object_space()->end();
heap->free_heap_physical_memory_after_fullgc(start, end);
}

if (UseAdaptiveSizePolicy) {

Expand Down Expand Up @@ -361,6 +366,9 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
if (PrintGCDetails) {
MetaspaceAux::print_metaspace_change(metadata_prev_used);
}
if (FreeHeapPhysicalMemory) {
heap->print_heap_physical_memory_free_info();
}
}

// Track memory usage and detect low memory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2100,6 +2100,11 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {

// Let the size policy know we're done
size_policy->major_collection_end(old_gen->used_in_bytes(), gc_cause);
if (FreeHeapPhysicalMemory) {
void* start = old_gen->object_space()->top();
void* end = old_gen->object_space()->end();
heap->free_heap_physical_memory_after_fullgc(start, end);
}

if (UseAdaptiveSizePolicy) {
if (PrintAdaptiveSizePolicy) {
Expand Down Expand Up @@ -2194,6 +2199,9 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
} else {
heap->print_heap_change(pre_gc_values.heap_used());
}
if (FreeHeapPhysicalMemory) {
heap->print_heap_physical_memory_free_info();
}
}

// Track memory usage and detect low memory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
#include "gc_implementation/parallelScavenge/psMarkSweepDecorator.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "gc_implementation/parallelScavenge/psTasks.hpp"
#include "gc_implementation/shared/gcHeapSummary.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ bool PSVirtualSpace::shrink_by(size_t bytes) {
bool result = special() || os::uncommit_memory(base_addr, bytes);
if (result) {
_committed_high_addr -= bytes;
if (FreeHeapPhysicalMemory) {
//should try to madvise virtual memory [base_addr, base_addr + bytes]
//only after os::uncommit_memory succeed
os::free_heap_physical_memory(base_addr, bytes);
}
}

return result;
Expand Down
Loading

0 comments on commit 4898f20

Please sign in to comment.