Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8252645: Change time measurements in G1ServiceThread to only account remembered set work #1447

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
70 changes: 49 additions & 21 deletions src/hotspot/share/gc/g1/g1RemSet.cpp
Expand Up @@ -482,27 +482,6 @@ class G1RemSetScanState : public CHeapObj<mtGC> {
}
};

G1RemSet::G1RemSet(G1CollectedHeap* g1h,
Copy link
Contributor

Choose a reason for hiding this comment

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

Not completely sure why this moved but not G1RemSet::initialize() below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The destructor had to move to see the type and I obviously took the constructor but missed initialize(). Certainly makes sense to move that one too.

G1CardTable* ct,
G1HotCardCache* hot_card_cache) :
_scan_state(new G1RemSetScanState()),
_prev_period_summary(false),
_g1h(g1h),
_ct(ct),
_g1p(_g1h->policy()),
_hot_card_cache(hot_card_cache),
_sampling_task(NULL) {
}

G1RemSet::~G1RemSet() {
delete _scan_state;
delete _sampling_task;
}

void G1RemSet::initialize(uint max_reserved_regions) {
_scan_state->initialize(max_reserved_regions);
}

class G1YoungRemSetSamplingClosure : public HeapRegionClosure {
SuspendibleThreadSetJoiner* _sts;
size_t _regions_visited;
Expand Down Expand Up @@ -537,6 +516,19 @@ class G1YoungRemSetSamplingClosure : public HeapRegionClosure {

// Task handling young gen remembered set sampling.
class G1RemSetSamplingTask : public G1ServiceTask {
// Helper to account virtual time.
class VTimer {
double _start;
public:
VTimer() : _start(os::elapsedVTime()) { }
double duration() { return os::elapsedVTime() - _start; }
};

double _vtime_accum; // Accumulated virtual time.
void update_vtime_accum(double duration) {
_vtime_accum += duration;
}

// Sample the current length of remembered sets for young.
//
// At the end of the GC G1 determines the length of the young gen based on
Expand All @@ -551,6 +543,7 @@ class G1RemSetSamplingTask : public G1ServiceTask {
void sample_young_list_rs_length(SuspendibleThreadSetJoiner* sts){
G1CollectedHeap* g1h = G1CollectedHeap::heap();
G1Policy* policy = g1h->policy();
VTimer vtime;

if (policy->use_adaptive_young_list_length()) {
G1YoungRemSetSamplingClosure cl(sts);
Expand All @@ -562,6 +555,7 @@ class G1RemSetSamplingTask : public G1ServiceTask {
policy->revise_young_list_target_length_if_necessary(cl.sampled_rs_length());
}
}
update_vtime_accum(vtime.duration());
}

// To avoid extensive rescheduling if the task is executed a bit early. The task is
Expand Down Expand Up @@ -596,14 +590,48 @@ class G1RemSetSamplingTask : public G1ServiceTask {
sample_young_list_rs_length(&sts);
schedule(G1ConcRefinementServiceIntervalMillis);
}

double vtime_accum() {
// Only report vtime if supported by the os.
if (!os::supports_vtime()) {
return 0.0;
}
return _vtime_accum;
}
};

G1RemSet::G1RemSet(G1CollectedHeap* g1h,
G1CardTable* ct,
G1HotCardCache* hot_card_cache) :
_scan_state(new G1RemSetScanState()),
_prev_period_summary(false),
_g1h(g1h),
_ct(ct),
_g1p(_g1h->policy()),
_hot_card_cache(hot_card_cache),
_sampling_task(NULL) {
}

G1RemSet::~G1RemSet() {
delete _scan_state;
delete _sampling_task;
}

void G1RemSet::initialize(uint max_reserved_regions) {
_scan_state->initialize(max_reserved_regions);
}

void G1RemSet::initialize_sampling_task(G1ServiceThread* thread) {
assert(_sampling_task == NULL, "Sampling task already initialized");
_sampling_task = new G1RemSetSamplingTask("Remembered Set Sampling Task");
thread->register_task(_sampling_task);
}

double G1RemSet::sampling_task_vtime() {
assert(_sampling_task != NULL, "Must have been initialized");
return _sampling_task->vtime_accum();
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Extra newline.

// Helper class to scan and detect ranges of cards that need to be scanned on the
// card table.
class G1CardTableScanner : public StackObj {
Expand Down
7 changes: 5 additions & 2 deletions src/hotspot/share/gc/g1/g1RemSet.hpp
Expand Up @@ -48,8 +48,8 @@ class G1RemSetScanState;
class G1ParScanThreadState;
class G1ParScanThreadStateSet;
class G1Policy;
class G1RemSetSamplingTask;
class G1ScanCardClosure;
class G1ServiceTask;
class G1ServiceThread;
class HeapRegionClaimer;

Expand All @@ -67,7 +67,7 @@ class G1RemSet: public CHeapObj<mtGC> {
G1CardTable* _ct;
G1Policy* _g1p;
G1HotCardCache* _hot_card_cache;
G1ServiceTask* _sampling_task;
G1RemSetSamplingTask* _sampling_task;

void print_merge_heap_roots_stats();

Expand All @@ -87,6 +87,9 @@ class G1RemSet: public CHeapObj<mtGC> {
// Initialize and schedule young remembered set sampling task.
void initialize_sampling_task(G1ServiceThread* thread);

// Accumulated vtime used by the sampling task.
double sampling_task_vtime();

// Scan all cards in the non-collection set regions that potentially contain
// references into the current whole collection set.
void scan_heap_roots(G1ParScanThreadState* pss,
Expand Down
13 changes: 6 additions & 7 deletions src/hotspot/share/gc/g1/g1RemSetSummary.cpp
Expand Up @@ -30,7 +30,6 @@
#include "gc/g1/g1DirtyCardQueue.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1RemSetSummary.hpp"
#include "gc/g1/g1ServiceThread.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "memory/allocation.inline.hpp"
Expand All @@ -53,7 +52,7 @@ void G1RemSetSummary::update() {
g1h->concurrent_refine()->threads_do(&collector);
_num_coarsenings = HeapRegionRemSet::n_coarsenings();

set_service_thread_vtime(g1h->service_thread()->vtime_accum());
set_sampling_task_vtime(g1h->rem_set()->sampling_task_vtime());
}

void G1RemSetSummary::set_rs_thread_vtime(uint thread, double value) {
Expand All @@ -72,7 +71,7 @@ G1RemSetSummary::G1RemSetSummary(bool should_update) :
_num_coarsenings(0),
_num_vtimes(G1ConcurrentRefine::max_num_threads()),
_rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
_service_thread_vtime(0.0f) {
_sampling_task_vtime(0.0f) {

memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes);

Expand All @@ -93,7 +92,7 @@ void G1RemSetSummary::set(G1RemSetSummary* other) {

memcpy(_rs_threads_vtimes, other->_rs_threads_vtimes, sizeof(double) * _num_vtimes);

set_service_thread_vtime(other->service_thread_vtime());
set_sampling_task_vtime(other->sampling_task_vtime());
}

void G1RemSetSummary::subtract_from(G1RemSetSummary* other) {
Expand All @@ -106,7 +105,7 @@ void G1RemSetSummary::subtract_from(G1RemSetSummary* other) {
set_rs_thread_vtime(i, other->rs_thread_vtime(i) - rs_thread_vtime(i));
}

_service_thread_vtime = other->service_thread_vtime() - _service_thread_vtime;
_sampling_task_vtime = other->sampling_task_vtime() - _sampling_task_vtime;
}

class RegionTypeCounter {
Expand Down Expand Up @@ -327,8 +326,8 @@ void G1RemSetSummary::print_on(outputStream* out) {
out->print(" %5.2f", rs_thread_vtime(i));
}
out->cr();
out->print_cr(" Service thread time (s)");
out->print_cr(" %5.2f", service_thread_vtime());
out->print_cr(" Sampling task time (ms)");
out->print_cr(" %5.3f", sampling_task_vtime() * MILLIUNITS);

HRRSStatsIter blk;
G1CollectedHeap::heap()->heap_region_iterate(&blk);
Expand Down
10 changes: 5 additions & 5 deletions src/hotspot/share/gc/g1/g1RemSetSummary.hpp
Expand Up @@ -38,11 +38,11 @@ class G1RemSetSummary {
size_t _num_vtimes;
double* _rs_threads_vtimes;

double _service_thread_vtime;
double _sampling_task_vtime;

void set_rs_thread_vtime(uint thread, double value);
void set_service_thread_vtime(double value) {
_service_thread_vtime = value;
void set_sampling_task_vtime(double value) {
_sampling_task_vtime = value;
}

// update this summary with current data from various places
Expand All @@ -62,8 +62,8 @@ class G1RemSetSummary {

double rs_thread_vtime(uint thread) const;

double service_thread_vtime() const {
return _service_thread_vtime;
double sampling_task_vtime() const {
return _sampling_task_vtime;
}

size_t num_coarsenings() const {
Expand Down
10 changes: 1 addition & 9 deletions src/hotspot/share/gc/g1/g1ServiceThread.cpp
Expand Up @@ -102,8 +102,7 @@ G1ServiceThread::G1ServiceThread() :
true,
Monitor::_safepoint_check_never),
_task_queue(),
_periodic_gc_task(new G1PeriodicGCTask("Periodic GC Task")),
_vtime_accum(0) {
_periodic_gc_task(new G1PeriodicGCTask("Periodic GC Task")) {
set_name("G1 Service");
create_and_start();
}
Expand Down Expand Up @@ -215,8 +214,6 @@ void G1ServiceThread::run_task(G1ServiceTask* task) {
}

void G1ServiceThread::run_service() {
double vtime_start = os::elapsedVTime();

// Register the tasks handled by the service thread.
register_task(_periodic_gc_task);

Expand All @@ -226,11 +223,6 @@ void G1ServiceThread::run_service() {
run_task(task);
}

if (os::supports_vtime()) {
_vtime_accum = (os::elapsedVTime() - vtime_start);
} else {
_vtime_accum = 0.0;
}
sleep_before_next_cycle();
}

Expand Down
3 changes: 0 additions & 3 deletions src/hotspot/share/gc/g1/g1ServiceThread.hpp
Expand Up @@ -107,8 +107,6 @@ class G1ServiceThread: public ConcurrentGCThread {

G1PeriodicGCTask* _periodic_gc_task;

double _vtime_accum; // Accumulated virtual time.

void run_service();
void stop_service();

Expand All @@ -133,7 +131,6 @@ class G1ServiceThread: public ConcurrentGCThread {
G1ServiceThread();
~G1ServiceThread();

double vtime_accum() { return _vtime_accum; }
// 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);
Expand Down