Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8255001: Move G1PeriodicGCTask to its own file
Reviewed-by: tschatzl, lkorinth
  • Loading branch information
kstefanj committed Nov 30, 2020
1 parent 8aaee53 commit 02ba519
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 72 deletions.
6 changes: 6 additions & 0 deletions src/hotspot/share/gc/g1/g1CollectedHeap.cpp
Expand Up @@ -52,6 +52,7 @@
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1ParallelCleaning.hpp"
#include "gc/g1/g1ParScanThreadState.inline.hpp"
#include "gc/g1/g1PeriodicGCTask.hpp"
#include "gc/g1/g1Policy.hpp"
#include "gc/g1/g1RedirtyCardsQueue.hpp"
#include "gc/g1/g1RegionToSpaceMapper.hpp"
Expand Down Expand Up @@ -1390,6 +1391,7 @@ class HumongousRegionSetChecker : public HeapRegionSetChecker {
G1CollectedHeap::G1CollectedHeap() :
CollectedHeap(),
_service_thread(NULL),
_periodic_gc_task(NULL),
_workers(NULL),
_card_table(NULL),
_collection_pause_end(Ticks::now()),
Expand Down Expand Up @@ -1689,6 +1691,10 @@ jint G1CollectedHeap::initialize() {
// Initialize and schedule sampling task on service thread.
_rem_set->initialize_sampling_task(service_thread());

// Create and schedule the periodic gc task on the service thread.
_periodic_gc_task = new G1PeriodicGCTask("Periodic GC Task");
_service_thread->register_task(_periodic_gc_task);

{
G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
dcqs.set_process_cards_threshold(concurrent_refine()->yellow_zone());
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/gc/g1/g1CollectedHeap.hpp
Expand Up @@ -79,6 +79,7 @@ class G1CollectionSet;
class G1Policy;
class G1HotCardCache;
class G1RemSet;
class G1ServiceTask;
class G1ServiceThread;
class G1ConcurrentMark;
class G1ConcurrentMarkThread;
Expand Down Expand Up @@ -154,6 +155,7 @@ class G1CollectedHeap : public CollectedHeap {

private:
G1ServiceThread* _service_thread;
G1ServiceTask* _periodic_gc_task;

WorkGang* _workers;
G1CardTable* _card_table;
Expand Down
86 changes: 86 additions & 0 deletions src/hotspot/share/gc/g1/g1PeriodicGCTask.cpp
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. 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.
*
*/

#include "precompiled.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentMark.inline.hpp"
#include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
#include "gc/g1/g1PeriodicGCTask.hpp"
#include "logging/log.hpp"
#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "utilities/globalDefinitions.hpp"

bool G1PeriodicGCTask::should_start_periodic_gc() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
// If we are currently in a concurrent mark we are going to uncommit memory soon.
if (g1h->concurrent_mark()->cm_thread()->in_progress()) {
log_debug(gc, periodic)("Concurrent cycle in progress. Skipping.");
return false;
}

// Check if enough time has passed since the last GC.
uintx time_since_last_gc = (uintx)g1h->time_since_last_collection().milliseconds();
if ((time_since_last_gc < G1PeriodicGCInterval)) {
log_debug(gc, periodic)("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.",
time_since_last_gc, G1PeriodicGCInterval);
return false;
}

// Check if load is lower than max.
double recent_load;
if ((G1PeriodicGCSystemLoadThreshold > 0.0f) &&
(os::loadavg(&recent_load, 1) == -1 || recent_load > G1PeriodicGCSystemLoadThreshold)) {
log_debug(gc, periodic)("Load %1.2f is higher than threshold %1.2f. Skipping.",
recent_load, G1PeriodicGCSystemLoadThreshold);
return false;
}
return true;
}

void G1PeriodicGCTask::check_for_periodic_gc() {
// If disabled, just return.
if (G1PeriodicGCInterval == 0) {
return;
}

log_debug(gc, periodic)("Checking for periodic GC.");
if (should_start_periodic_gc()) {
if (!G1CollectedHeap::heap()->try_collect(GCCause::_g1_periodic_collection)) {
log_debug(gc, periodic)("GC request denied. Skipping.");
}
}
}

G1PeriodicGCTask::G1PeriodicGCTask(const char* name) :
G1ServiceTask(name) { }

void G1PeriodicGCTask::execute() {
check_for_periodic_gc();
// G1PeriodicGCInterval is a manageable flag and can be updated
// during runtime. If no value is set, wait a second and run it
// again to see if the value has been updated. Otherwise use the
// real value provided.
schedule(G1PeriodicGCInterval == 0 ? 1000 : G1PeriodicGCInterval);
}
40 changes: 40 additions & 0 deletions src/hotspot/share/gc/g1/g1PeriodicGCTask.hpp
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. 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.
*
*/

#ifndef SHARE_GC_G1_G1PERIODICGCTASK_HPP
#define SHARE_GC_G1_G1PERIODICGCTASK_HPP

#include "gc/g1/g1ServiceThread.hpp"

// Task handling periodic GCs
class G1PeriodicGCTask : public G1ServiceTask {
bool should_start_periodic_gc();
void check_for_periodic_gc();

public:
G1PeriodicGCTask(const char* name);
virtual void execute();
};

#endif // SHARE_GC_G1_G1PERIODICGCTASK_HPP
71 changes: 3 additions & 68 deletions src/hotspot/share/gc/g1/g1ServiceThread.cpp
Expand Up @@ -23,12 +23,10 @@
*/

#include "precompiled.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentMark.inline.hpp"
#include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
#include "gc/g1/g1ServiceThread.hpp"
#include "memory/universe.hpp"
#include "logging/log.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/timer.hpp"
#include "runtime/os.hpp"

G1SentinelTask::G1SentinelTask() : G1ServiceTask("Sentinel Task") {
Expand All @@ -40,77 +38,17 @@ void G1SentinelTask::execute() {
guarantee(false, "Sentinel service task should never be executed.");
}

// Task handling periodic GCs
class G1PeriodicGCTask : public G1ServiceTask {
bool should_start_periodic_gc() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
// If we are currently in a concurrent mark we are going to uncommit memory soon.
if (g1h->concurrent_mark()->cm_thread()->in_progress()) {
log_debug(gc, periodic)("Concurrent cycle in progress. Skipping.");
return false;
}

// Check if enough time has passed since the last GC.
uintx time_since_last_gc = (uintx)g1h->time_since_last_collection().milliseconds();
if ((time_since_last_gc < G1PeriodicGCInterval)) {
log_debug(gc, periodic)("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.",
time_since_last_gc, G1PeriodicGCInterval);
return false;
}

// Check if load is lower than max.
double recent_load;
if ((G1PeriodicGCSystemLoadThreshold > 0.0f) &&
(os::loadavg(&recent_load, 1) == -1 || recent_load > G1PeriodicGCSystemLoadThreshold)) {
log_debug(gc, periodic)("Load %1.2f is higher than threshold %1.2f. Skipping.",
recent_load, G1PeriodicGCSystemLoadThreshold);
return false;
}
return true;
}

void check_for_periodic_gc(){
// If disabled, just return.
if (G1PeriodicGCInterval == 0) {
return;
}

log_debug(gc, periodic)("Checking for periodic GC.");
if (should_start_periodic_gc()) {
if (!G1CollectedHeap::heap()->try_collect(GCCause::_g1_periodic_collection)) {
log_debug(gc, periodic)("GC request denied. Skipping.");
}
}
}
public:
G1PeriodicGCTask(const char* name) : G1ServiceTask(name) { }

virtual void execute() {
check_for_periodic_gc();
// G1PeriodicGCInterval is a manageable flag and can be updated
// during runtime. If no value is set, wait a second and run it
// again to see if the value has been updated. Otherwise use the
// real value provided.
schedule(G1PeriodicGCInterval == 0 ? 1000 : G1PeriodicGCInterval);
}
};

G1ServiceThread::G1ServiceThread() :
ConcurrentGCThread(),
_monitor(Mutex::nonleaf,
"G1ServiceThread monitor",
true,
Monitor::_safepoint_check_never),
_task_queue(),
_periodic_gc_task(new G1PeriodicGCTask("Periodic GC Task")) {
_task_queue() {
set_name("G1 Service");
create_and_start();
}

G1ServiceThread::~G1ServiceThread() {
delete _periodic_gc_task;
}

void G1ServiceThread::register_task(G1ServiceTask* task, jlong delay_ms) {
guarantee(!task->is_registered(), "Task already registered");
guarantee(task->next() == NULL, "Task already in queue");
Expand Down Expand Up @@ -215,9 +153,6 @@ void G1ServiceThread::run_task(G1ServiceTask* task) {
}

void G1ServiceThread::run_service() {
// Register the tasks handled by the service thread.
register_task(_periodic_gc_task);

while (!should_terminate()) {
G1ServiceTask* task = pop_due_task();
if (task != NULL) {
Expand Down
4 changes: 0 additions & 4 deletions src/hotspot/share/gc/g1/g1ServiceThread.hpp
Expand Up @@ -28,7 +28,6 @@
#include "gc/shared/concurrentGCThread.hpp"
#include "runtime/mutex.hpp"

class G1PeriodicGCTask;
class G1ServiceTaskQueue;
class G1ServiceThread;

Expand Down Expand Up @@ -105,8 +104,6 @@ class G1ServiceThread: public ConcurrentGCThread {
Monitor _monitor;
G1ServiceTaskQueue _task_queue;

G1PeriodicGCTask* _periodic_gc_task;

void run_service();
void stop_service();

Expand All @@ -129,7 +126,6 @@ class G1ServiceThread: public ConcurrentGCThread {

public:
G1ServiceThread();
~G1ServiceThread();

// Register a task with the service thread. The task is guaranteed not to run
// until at least `delay_ms` has passed. If no delay is specified or the
Expand Down

1 comment on commit 02ba519

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.