8252888: Collapse G1MMUTracker class hierarchy

Reviewed-by: ayang, sjohanss, kbarrett
This commit is contained in:
John Tortugo 2020-09-29 08:15:41 +00:00 committed by Stefan Johansson
parent e63b90cc17
commit b65913249f
3 changed files with 59 additions and 72 deletions

View File

@ -39,15 +39,12 @@
G1MMUTracker::G1MMUTracker(double time_slice, double max_gc_time) :
_time_slice(time_slice),
_max_gc_time(max_gc_time) { }
G1MMUTrackerQueue::G1MMUTrackerQueue(double time_slice, double max_gc_time) :
G1MMUTracker(time_slice, max_gc_time),
_max_gc_time(max_gc_time),
_head_index(0),
_tail_index(trim_index(_head_index+1)),
_no_entries(0) { }
void G1MMUTrackerQueue::remove_expired_entries(double current_time) {
void G1MMUTracker::remove_expired_entries(double current_time) {
double limit = current_time - _time_slice;
while (_no_entries > 0) {
if (is_double_geq(limit, _array[_tail_index].end_time())) {
@ -59,12 +56,12 @@ void G1MMUTrackerQueue::remove_expired_entries(double current_time) {
guarantee(_no_entries == 0, "should have no entries in the array");
}
double G1MMUTrackerQueue::calculate_gc_time(double current_time) {
double G1MMUTracker::calculate_gc_time(double current_time) {
double gc_time = 0.0;
double limit = current_time - _time_slice;
for (int i = 0; i < _no_entries; ++i) {
int index = trim_index(_tail_index + i);
G1MMUTrackerQueueElem *elem = &_array[index];
G1MMUTrackerElem *elem = &_array[index];
if (elem->end_time() > limit) {
if (elem->start_time() > limit)
gc_time += elem->duration();
@ -75,7 +72,7 @@ double G1MMUTrackerQueue::calculate_gc_time(double current_time) {
return gc_time;
}
void G1MMUTrackerQueue::add_pause(double start, double end) {
void G1MMUTracker::add_pause(double start, double end) {
remove_expired_entries(end);
if (_no_entries == QueueLength) {
// OK, we've filled up the queue. There are a few ways
@ -99,7 +96,7 @@ void G1MMUTrackerQueue::add_pause(double start, double end) {
_head_index = trim_index(_head_index + 1);
++_no_entries;
}
_array[_head_index] = G1MMUTrackerQueueElem(start, end);
_array[_head_index] = G1MMUTrackerElem(start, end);
// Current entry needs to be added before calculating the value
double slice_time = calculate_gc_time(end);
@ -114,7 +111,7 @@ void G1MMUTrackerQueue::add_pause(double start, double end) {
}
}
double G1MMUTrackerQueue::when_sec(double current_time, double pause_time) {
double G1MMUTracker::when_sec(double current_time, double pause_time) {
// if the pause is over the maximum, just assume that it's the maximum
double adjusted_pause_time =
(pause_time > max_gc_time()) ? max_gc_time() : pause_time;
@ -126,13 +123,13 @@ double G1MMUTrackerQueue::when_sec(double current_time, double pause_time) {
return 0.0;
if (adjusted_pause_time == max_gc_time()) {
G1MMUTrackerQueueElem *elem = &_array[_head_index];
G1MMUTrackerElem *elem = &_array[_head_index];
return elem->end_time() - limit;
}
int index = _tail_index;
while ( 1 ) {
G1MMUTrackerQueueElem *elem = &_array[index];
G1MMUTrackerElem *elem = &_array[index];
if (elem->end_time() > limit) {
if (elem->start_time() > limit)
diff -= elem->duration();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 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
@ -29,9 +29,31 @@
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
// Two major user controls over G1 behavior are setting a pause time goal (MaxGCPauseMillis),
// over a time slice (GCPauseIntervalMillis). This defines the Minimum Mutator
// Utilisation (MMU) goal.
class G1MMUTrackerElem {
private:
double _start_time;
double _end_time;
public:
inline double start_time() { return _start_time; }
inline double end_time() { return _end_time; }
inline double duration() { return _end_time - _start_time; }
G1MMUTrackerElem() {
_start_time = 0.0;
_end_time = 0.0;
}
G1MMUTrackerElem(double start_time, double end_time) {
_start_time = start_time;
_end_time = end_time;
}
};
// Two major user controls over G1 behavior are setting a pause
// time goal (MaxGCPauseMillis), over a time slice (GCPauseIntervalMillis).
// This defines the Minimum Mutator Utilisation (MMU) goal.
//
// * Definitions *
// Mutator Utilisation:
@ -42,60 +64,20 @@
// Minimum Mutator Utilisation (MMU):
// - the worst mutator utilisation across all time slices.
//
// G1MMUTracker keeps track of the GC work and decides when it is OK to do GC work
// and for how long so that the MMU invariants are maintained.
// The G1MMUTracker uses a fixed-size queue to keep track of all
// recent pause times. The pause time data is used to avoid
// breaking the MMU.
//
// ***** ALL TIMES ARE IN SECS!!!!!!! *****
// this is the "interface"
class G1MMUTracker: public CHeapObj<mtGC> {
protected:
double _time_slice;
double _max_gc_time; // this is per time slice
public:
G1MMUTracker(double time_slice, double max_gc_time);
virtual void add_pause(double start, double end) = 0;
virtual double when_sec(double current_time, double pause_time) = 0;
double max_gc_time() const {
return _max_gc_time;
}
inline double when_max_gc_sec(double current_time) {
return when_sec(current_time, max_gc_time());
}
};
class G1MMUTrackerQueueElem {
private:
double _start_time;
double _end_time;
public:
inline double start_time() { return _start_time; }
inline double end_time() { return _end_time; }
inline double duration() { return _end_time - _start_time; }
G1MMUTrackerQueueElem() {
_start_time = 0.0;
_end_time = 0.0;
}
G1MMUTrackerQueueElem(double start_time, double end_time) {
_start_time = start_time;
_end_time = end_time;
}
};
// this is an implementation of the MMUTracker using a (fixed-size) queue
// that keeps track of all the recent pause times
class G1MMUTrackerQueue: public G1MMUTracker {
private:
enum PrivateConstants {
QueueLength = 64
};
double _time_slice;
double _max_gc_time; // this is per time slice
// The array keeps track of all the pauses that fall within a time
// slice (the last time slice during which pauses took place).
// The data structure implemented is a circular queue.
@ -105,13 +87,13 @@ private:
// If the array is full, an easy fix is to look for the pauses with
// the shortest gap between them and consolidate them.
// For now, we have taken the expedient alternative of forgetting
// the oldest entry in the event that +G1UseFixedWindowMMUTracker, thus
// potentially violating MMU specs for some time thereafter.
// the oldest entry, thus potentially violating MMU specs for
// some time thereafter.
G1MMUTrackerQueueElem _array[QueueLength];
int _head_index;
int _tail_index;
int _no_entries;
G1MMUTrackerElem _array[QueueLength];
int _head_index;
int _tail_index;
int _no_entries;
inline int trim_index(int index) {
return (index + QueueLength) % QueueLength;
@ -121,11 +103,19 @@ private:
double calculate_gc_time(double current_time);
public:
G1MMUTrackerQueue(double time_slice, double max_gc_time);
G1MMUTracker(double time_slice, double max_gc_time);
virtual void add_pause(double start, double end);
void add_pause(double start, double end);
virtual double when_sec(double current_time, double pause_time);
double when_sec(double current_time, double pause_time);
double max_gc_time() const {
return _max_gc_time;
}
double when_max_gc_sec(double current_time) {
return when_sec(current_time, max_gc_time());
}
};
#endif // SHARE_GC_G1_G1MMUTRACKER_HPP

View File

@ -56,7 +56,7 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) :
_predictor(G1ConfidencePercent / 100.0),
_analytics(new G1Analytics(&_predictor)),
_remset_tracker(),
_mmu_tracker(new G1MMUTrackerQueue(GCPauseIntervalMillis / 1000.0, MaxGCPauseMillis / 1000.0)),
_mmu_tracker(new G1MMUTracker(GCPauseIntervalMillis / 1000.0, MaxGCPauseMillis / 1000.0)),
_old_gen_alloc_tracker(),
_ihop_control(create_ihop_control(&_old_gen_alloc_tracker, &_predictor)),
_policy_counters(new GCPolicyCounters("GarbageFirst", 1, 2)),