Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
8252888: Collapse G1MMUTracker class hierarchy
Reviewed-by: ayang, sjohanss, kbarrett
  • Loading branch information
JohnTortugo authored and kstefanj committed Sep 29, 2020
1 parent e63b90c commit b65913249f58e4bfbdf383d5e46e3e014c9b1c47
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 67 deletions.
@@ -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,45 +29,7 @@
#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.
//
// * Definitions *
// Mutator Utilisation:
// - for a given time slice duration "ts",
// - mutator utilisation is the following fraction:
// non_gc_time / ts
//
// 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.
//
// ***** 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 {
class G1MMUTrackerElem {
private:
double _start_time;
double _end_time;
@@ -77,25 +39,45 @@ class G1MMUTrackerQueueElem {
inline double end_time() { return _end_time; }
inline double duration() { return _end_time - _start_time; }

G1MMUTrackerQueueElem() {
G1MMUTrackerElem() {
_start_time = 0.0;
_end_time = 0.0;
}

G1MMUTrackerQueueElem(double start_time, double end_time) {
G1MMUTrackerElem(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 {

// 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:
// - for a given time slice duration "ts",
// - mutator utilisation is the following fraction:
// non_gc_time / ts
//
// Minimum Mutator Utilisation (MMU):
// - the worst mutator utilisation across all time slices.
//
// 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!!!!!!! *****
class G1MMUTracker: public CHeapObj<mtGC> {
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 @@ class G1MMUTrackerQueue: public G1MMUTracker {
// 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 @@ class G1MMUTrackerQueue: public G1MMUTracker {
double calculate_gc_time(double current_time);

public:
G1MMUTrackerQueue(double time_slice, double max_gc_time);
G1MMUTracker(double time_slice, double max_gc_time);

void add_pause(double start, double end);

virtual void add_pause(double start, double end);
double when_sec(double current_time, double pause_time);

virtual 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)),

0 comments on commit b659132

Please sign in to comment.