8252888: Collapse G1MMUTracker class hierarchy
Reviewed-by: ayang, sjohanss, kbarrett
This commit is contained in:
parent
e63b90cc17
commit
b65913249f
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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)),
|
||||
|
Loading…
x
Reference in New Issue
Block a user