Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
8257149: Improve G1 Service thread task scheduling to guarantee task …
…delay

Reviewed-by: sjohanss, iwalulya
  • Loading branch information
albertnetymk authored and kstefanj committed Nov 27, 2020
1 parent f2f3ba9 commit 20525d2110a7bb028610a2a4dac53f3c02365e49
Showing with 16 additions and 20 deletions.
  1. +3 −9 src/hotspot/share/gc/g1/g1RemSet.cpp
  2. +5 −4 src/hotspot/share/gc/g1/g1ServiceThread.cpp
  3. +8 −7 src/hotspot/share/gc/g1/g1ServiceThread.hpp
@@ -558,12 +558,6 @@ class G1RemSetSamplingTask : public G1ServiceTask {
update_vtime_accum(vtime.duration());
}

// To avoid extensive rescheduling if the task is executed a bit early. The task is
// only rescheduled if the expected time is more than 1ms away.
bool should_reschedule() {
return reschedule_delay_ms() > 1;
}

// There is no reason to do the sampling if a GC occurred recently. We use the
// G1ConcRefinementServiceIntervalMillis as the metric for recently and calculate
// the diff to the last GC. If the last GC occurred longer ago than the interval
@@ -580,9 +574,9 @@ class G1RemSetSamplingTask : public G1ServiceTask {
SuspendibleThreadSetJoiner sts;

// Reschedule if a GC happened too recently.
if (should_reschedule()) {
// Calculate the delay given the last GC and the interval.
schedule(reschedule_delay_ms());
jlong delay_ms = reschedule_delay_ms();
if (delay_ms > 0) {
schedule(delay_ms);
return;
}

@@ -111,7 +111,7 @@ G1ServiceThread::~G1ServiceThread() {
delete _periodic_gc_task;
}

void G1ServiceThread::register_task(G1ServiceTask* task, jlong delay) {
void G1ServiceThread::register_task(G1ServiceTask* task, jlong delay_ms) {
guarantee(!task->is_registered(), "Task already registered");
guarantee(task->next() == NULL, "Task already in queue");

@@ -130,7 +130,7 @@ void G1ServiceThread::register_task(G1ServiceTask* task, jlong delay) {

// Schedule the task to run after the given delay. The service will be
// notified to check if this task is first in the queue.
schedule_task(task, delay);
schedule_task(task, delay_ms);
}

void G1ServiceThread::schedule(G1ServiceTask* task, jlong delay_ms) {
@@ -163,8 +163,9 @@ int64_t G1ServiceThread::time_to_next_task_ms() {
return 0;
}

// Return sleep time in milliseconds.
return (int64_t) TimeHelper::counter_to_millis(time_diff);
// Return sleep time in milliseconds. Using ceil to make sure we never
// schedule a task too early.
return (int64_t) ceil(TimeHelper::counter_to_millis(time_diff));
}

void G1ServiceThread::notify() {
@@ -131,13 +131,14 @@ class G1ServiceThread: public ConcurrentGCThread {
G1ServiceThread();
~G1ServiceThread();

// Register a task with the service thread and schedule it. If
// no delay is specified the task is scheduled to run directly.
void register_task(G1ServiceTask* task, jlong delay = 0);

// Schedule the task and notify the service thread that a new
// task might be ready to run.
void schedule_task(G1ServiceTask* task, jlong delay);
// 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
// delay is 0, the task will run in the earliest time possible.
void register_task(G1ServiceTask* task, jlong delay_ms = 0);

// Schedule an already-registered task to run in at least `delay_ms` time,
// and notify the service thread.
void schedule_task(G1ServiceTask* task, jlong delay_ms);
};

#endif // SHARE_GC_G1_G1SERVICETHREAD_HPP

0 comments on commit 20525d2

Please sign in to comment.