Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
03bd55e
trim-native
tstuefe Aug 30, 2022
4b843df
some simplifications
tstuefe Aug 30, 2022
7c7a3e0
Fixes and Simplifications
tstuefe Aug 30, 2022
864b3fb
wip
tstuefe Aug 31, 2022
cbf027a
make tests more stable on slow hardware
tstuefe Sep 1, 2022
35938c6
reduce test runtime on slow hardware
tstuefe Sep 1, 2022
c8b99d8
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Oct 19, 2022
40b3e36
Make test more fault tolerant
tstuefe Oct 19, 2022
7851dae
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Nov 2, 2022
02baff8
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Nov 10, 2022
b9d6c71
merge
tstuefe Jan 12, 2023
5b997d6
Fix merge errors
tstuefe Jan 12, 2023
1b47718
merge-master-with-fixes
tstuefe Jan 24, 2023
0cfacb9
Merge
tstuefe Jan 25, 2023
a8ae8a2
make tests for ppc more lenient
tstuefe Jan 25, 2023
5d5610d
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Jan 26, 2023
6f1092c
revamp wip
tstuefe Jan 27, 2023
245a62a
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Jan 27, 2023
7dc36c1
wip
tstuefe Jan 28, 2023
94643a7
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Jan 28, 2023
943ab23
wip
tstuefe Jan 30, 2023
486cd1b
wip
tstuefe Jan 31, 2023
599573d
wip
tstuefe Feb 1, 2023
df3f777
wip
tstuefe Feb 1, 2023
c765621
src/hotspot/share/gc/shared/gcTrimNativeHeap.cpp
tstuefe Feb 1, 2023
9811577
rename
tstuefe Feb 2, 2023
f4140df
rename NativeTrimmer
tstuefe Feb 2, 2023
0359343
rename GCTrimNative TrimNative
tstuefe Feb 2, 2023
55386d2
wip
tstuefe Feb 2, 2023
db0a8ba
wip
tstuefe Mar 1, 2023
018dda9
merge master
tstuefe Mar 1, 2023
d95d1f4
wip
tstuefe Mar 1, 2023
87937b4
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Mar 2, 2023
5d41312
wip
tstuefe Mar 2, 2023
1e49fcf
Merge master
tstuefe Jul 4, 2023
aa9b2a7
Remove adaptive stepdown coding
tstuefe Jul 4, 2023
a451dc5
wip
tstuefe Jul 4, 2023
92b5a41
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Jul 5, 2023
a4837e1
wip
tstuefe Jul 5, 2023
eaf2457
Merge branch 'master' into JDK-8293114-GC-trim-native
tstuefe Jul 5, 2023
162b880
fix windows build
tstuefe Jul 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/hotspot/share/classfile/stringTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "gc/shared/oopStorage.inline.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "gc/shared/stringdedup/stringDedup.hpp"
#include "gc/shared/trimNative.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
Expand Down Expand Up @@ -456,6 +457,7 @@ void StringTable::clean_dead_entries(JavaThread* jt) {

StringTableDeleteCheck stdc;
StringTableDoDelete stdd;
TrimNative::PauseMark trim_native_pause("stringtable");
{
TraceTime timer("Clean", TRACETIME_LOG(Debug, stringtable, perf));
while(bdt.do_task(jt, stdc, stdd)) {
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/classfile/symbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "classfile/compactHashtable.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "gc/shared/trimNative.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
Expand Down Expand Up @@ -737,6 +738,7 @@ void SymbolTable::clean_dead_entries(JavaThread* jt) {

SymbolTableDeleteCheck stdc;
SymbolTableDoDelete stdd;
TrimNative::PauseMark trim_native_pause("symboltable");
{
TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf));
while (bdt.do_task(jt, stdc, stdd)) {
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/gc/g1/g1CollectedHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#include "gc/shared/taskqueue.inline.hpp"
#include "gc/shared/taskTerminator.hpp"
#include "gc/shared/tlab_globals.hpp"
#include "gc/shared/trimNative.hpp"
#include "gc/shared/workerPolicy.hpp"
#include "gc/shared/weakProcessor.inline.hpp"
#include "logging/log.hpp"
Expand Down Expand Up @@ -914,6 +915,8 @@ bool G1CollectedHeap::do_full_collection(bool clear_all_soft_refs,
return false;
}

TrimNative::PauseMark trim_native_pause("gc");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of whack-a-mole game of putting the pause in most GC safepoint ops, we should "just" put this mark straight into VMOperation, so that all safepoint ops are covered? Or, if we want to limit to GC ops, VM_GC_Operation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this is a good idea.


const bool do_clear_all_soft_refs = clear_all_soft_refs ||
soft_ref_policy()->should_clear_all_soft_refs();

Expand Down Expand Up @@ -2549,6 +2552,7 @@ void G1CollectedHeap::retire_tlabs() {

void G1CollectedHeap::do_collection_pause_at_safepoint_helper() {
ResourceMark rm;
TrimNative::PauseMark trim_native_pause("gc");

IsGCActiveMark active_gc_mark;
GCIdMark gc_id_mark;
Expand Down
5 changes: 5 additions & 0 deletions src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/shared/taskTerminator.hpp"
#include "gc/shared/taskqueue.inline.hpp"
#include "gc/shared/trimNative.hpp"
#include "gc/shared/weakProcessor.inline.hpp"
#include "gc/shared/workerPolicy.hpp"
#include "jvm.h"
Expand Down Expand Up @@ -1234,6 +1235,8 @@ void G1ConcurrentMark::remark() {
return;
}

TrimNative::PauseMark trim_native_pause("gc");

G1Policy* policy = _g1h->policy();
policy->record_concurrent_mark_remark_start();

Expand Down Expand Up @@ -1448,6 +1451,8 @@ void G1ConcurrentMark::cleanup() {
return;
}

TrimNative::PauseMark trim_native_pause("gc");

G1Policy* policy = _g1h->policy();
policy->record_concurrent_mark_cleanup_start();

Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/gc/g1/g1FullCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class PrepareRegionsClosure : public HeapRegionClosure {
};

void G1FullCollector::prepare_collection() {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant.

_heap->policy()->record_full_collection_start();

// Verification needs the bitmap, so we should clear the bitmap only later.
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/gc/parallel/psParallelCompact.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/trimNative.hpp"
#include "gc/shared/isGCActiveMark.hpp"
#include "gc/shared/oopStorage.inline.hpp"
#include "gc/shared/oopStorageSet.inline.hpp"
Expand Down Expand Up @@ -1709,6 +1710,9 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
return false;
}

// Pause native trimming for the duration of the GC
TrimNative::PauseMark trim_native_pause("gc");

ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();

GCIdMark gc_id_mark;
Expand Down
15 changes: 13 additions & 2 deletions src/hotspot/share/gc/shared/gc_globals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,8 +690,19 @@
product(uint, GCCardSizeInBytes, 512, \
"Card table entry size (in bytes) for card based collectors") \
range(128, NOT_LP64(512) LP64_ONLY(1024)) \
constraint(GCCardSizeInBytesConstraintFunc,AtParse)
// end of GC_FLAGS
constraint(GCCardSizeInBytesConstraintFunc,AtParse) \
\
product(bool, TrimNativeHeap, false, EXPERIMENTAL, \
"GC will attempt to trim the native heap periodically. By " \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not trimmed by GC anymore, right? By a separate thread now?

I would also avoid mentioning the default here, just refer to TrimNativeHeapInterval. Saves the headache when default actually changes.

"default, the interval time is 60 seconds, but can be " \
"changed using TrimNativeHeapInterval.") \
\
product(uint, TrimNativeHeapInterval, 60, EXPERIMENTAL, \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most intervals like these are in milliseconds in Hotspot. Actually, I think it would be useful to have the sub-second interval for some short-lived workloads.

"If TrimNativeHeap is enabled: interval, in seconds, in which " \
"the GC will attempt to trim the native heap.") \
range(1, UINT_MAX) \
\
// end of GC_FLAGS

DECLARE_FLAGS(GC_FLAGS)

Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/gc/shared/genCollectedHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include "gc/shared/scavengableNMethods.hpp"
#include "gc/shared/space.hpp"
#include "gc/shared/strongRootsScope.hpp"
#include "gc/shared/trimNative.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "gc/shared/workerThread.hpp"
#include "memory/iterator.hpp"
Expand Down Expand Up @@ -442,6 +443,8 @@ void GenCollectedHeap::do_collection(bool full,
"the requesting thread should have the Heap_lock");
guarantee(!is_gc_active(), "collection is not reentrant");

TrimNative::PauseMark trim_native_pause("gc");

if (GCLocker::check_active_before_gc()) {
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
}
Expand Down
202 changes: 202 additions & 0 deletions src/hotspot/share/gc/shared/trimNative.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/*
* Copyright (c) 2023 SAP SE. All rights reserved.
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
*
* 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
* questioSns.
*
*/

#include "precompiled.hpp"
#include "gc/shared/concurrentGCThread.hpp"
#include "gc/shared/gc_globals.hpp"
#include "gc/shared/trimNative.hpp"
#include "logging/log.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ticks.hpp"

class NativeTrimmerThread : public ConcurrentGCThread {

Monitor* _lock;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const?


int64_t _next_trim_time;

// Pausing
int _pausers;
int64_t _next_trim_time_saved;

static const int64_t never = INT64_MAX;

static int64_t now() { return os::javaTimeMillis(); }

void run_service() override {

log_info(gc, trim)("NativeTrimmer start.");

int64_t ntt = 0;
int64_t tnow = 0;

for (;;) {
// 1 - Wait for _next_trim_time. Handle spurious wakeups and shutdown.
{
MonitorLocker ml(_lock, Mutex::_no_safepoint_check_flag);
do {
tnow = now();
ntt = _next_trim_time;
if (ntt == never) {
ml.wait(0); // infinite sleep
} else if (ntt > tnow) {
ml.wait(ntt - tnow); // sleep till next point
}
if (should_terminate()) {
log_info(gc, trim)("NativeTrimmer stop.");
return;
}
tnow = now();
ntt = _next_trim_time;
} while (ntt > tnow);
}

// 2 - Trim outside of lock protection.
execute_trim_and_log();

// 3 - Update _next_trim_time; but give concurrent setters preference.
{
MonitorLocker ml(_lock, Mutex::_no_safepoint_check_flag);
tnow = now();
int64_t ntt2 = _next_trim_time;

if (ntt2 == ntt) { // not changed concurrently?
_next_trim_time = tnow + (TrimNativeHeapInterval * 1000);
}
} // Mutex scope
}
}

void stop_service() override {
MonitorLocker ml(_lock, Mutex::_no_safepoint_check_flag);
ml.notify_all();
}

// Execute the native trim, log results.
void execute_trim_and_log() const {
assert(os::can_trim_native_heap(), "Unexpected");
const int64_t tnow = now();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line looks redundant.

os::size_change_t sc;
Ticks start = Ticks::now();
log_debug(gc, trim)("Trim native heap started...");
if (os::trim_native_heap(&sc)) {
Tickspan trim_time = (Ticks::now() - start);
if (sc.after != SIZE_MAX) {
const size_t delta = sc.after < sc.before ? (sc.before - sc.after) : (sc.after - sc.before);
const char sign = sc.after < sc.before ? '-' : '+';
log_info(gc, trim)("Trim native heap: RSS+Swap: " PROPERFMT "->" PROPERFMT " (%c" PROPERFMT "), %1.3fms",
PROPERFMTARGS(sc.before), PROPERFMTARGS(sc.after), sign, PROPERFMTARGS(delta),
trim_time.seconds() * 1000);
} else {
log_info(gc, trim)("Trim native heap (no details)");
}
}
}

public:

NativeTrimmerThread() :
_lock(new (std::nothrow) PaddedMonitor(Mutex::nosafepoint, "NativeTrimmer_lock")),
_next_trim_time(0),
_pausers(0),
_next_trim_time_saved(0)
{
set_name("Native Heap Trimmer");
_next_trim_time = now() + TrimNativeHeapInterval * 1000;
create_and_start();
}

void pause(const char* reason) {
assert(TrimNativeHeap, "Only call if enabled");
assert(TrimNativeHeapInterval > 0, "Only call if periodic trimming is enabled");
int lvl = 0;
{
MonitorLocker ml(_lock, Mutex::_no_safepoint_check_flag);
if (_pausers == 0) {
_next_trim_time_saved = _next_trim_time;
_next_trim_time = never;
}
lvl = ++_pausers;
// No need to wakeup trimmer
}
log_debug(gc, trim)("NativeTrimmer pause (%s) (%d)", reason, lvl);
}

void unpause(const char* reason) {
assert(TrimNativeHeap, "Only call if enabled");
assert(TrimNativeHeapInterval > 0, "Only call if periodic trimming is enabled");
int lvl = 0;
{
MonitorLocker ml(_lock, Mutex::_no_safepoint_check_flag);
lvl = _pausers--;
if (_pausers == 0) {
_next_trim_time = _next_trim_time_saved;
_next_trim_time_saved = 0;
ml.notify_all();
}
}
log_debug(gc, trim)("NativeTrimmer unpause (%s) (%d)", reason, lvl);
}

}; // NativeTrimmer

static NativeTrimmerThread* g_trimmer_thread = nullptr;

/// GCTrimNative outside facing methods

void TrimNative::initialize() {
if (TrimNativeHeap) {
if (!os::can_trim_native_heap()) {
FLAG_SET_ERGO(TrimNativeHeap, false);
log_info(gc, trim)("Native trim not supported on this platform.");
return;
}
g_trimmer_thread = new NativeTrimmerThread();
log_info(gc, trim)("Periodic native trim enabled (interval: %u seconds)", TrimNativeHeapInterval);
}
}

void TrimNative::cleanup() {
if (g_trimmer_thread != nullptr) {
g_trimmer_thread->stop();
}
}

void TrimNative::pause_periodic_trim(const char* reason) {
if (g_trimmer_thread != nullptr) {
g_trimmer_thread->pause(reason);
}
}

void TrimNative::unpause_periodic_trim(const char* reason) {
if (g_trimmer_thread != nullptr) {
g_trimmer_thread->unpause(reason);
}
}

Loading