1 /* 2 * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_GC_G1_G1MMUTRACKER_HPP 26 #define SHARE_VM_GC_G1_G1MMUTRACKER_HPP 27 28 #include "gc/shared/gcId.hpp" 29 #include "memory/allocation.hpp" 30 #include "utilities/debug.hpp" 31 32 // Two major user controls over G1 behavior are setting a pause time goal (MaxGCPauseMillis), 33 // over a time slice (GCPauseIntervalMillis). This defines the Minimum Mutator 34 // Utilisation (MMU) goal. 35 // 36 // * Definitions * 37 // Mutator Utilisation: 38 // - for a given time slice duration "ts", 39 // - mutator utilisation is the following fraction: 40 // non_gc_time / ts 41 // 42 // Minimum Mutator Utilisation (MMU): 43 // - the worst mutator utilisation across all time slices. 44 // 45 // G1MMUTracker keeps track of the GC work and decides when it is OK to do GC work 46 // and for how long so that the MMU invariants are maintained. 47 // 48 // ***** ALL TIMES ARE IN SECS!!!!!!! ***** 49 // this is the "interface" 50 class G1MMUTracker: public CHeapObj<mtGC> { 51 protected: 52 double _time_slice; 53 double _max_gc_time; // this is per time slice 54 55 public: 56 G1MMUTracker(double time_slice, double max_gc_time); 57 58 virtual void add_pause(double start, double end) = 0; 59 virtual double when_sec(double current_time, double pause_time) = 0; 60 61 double max_gc_time() const { 62 return _max_gc_time; 63 } 64 65 inline bool now_max_gc(double current_time) { 66 return when_sec(current_time, max_gc_time()) < 0.00001; 67 } 68 69 inline double when_max_gc_sec(double current_time) { 70 return when_sec(current_time, max_gc_time()); 71 } 72 73 inline jlong when_max_gc_ms(double current_time) { 74 double when = when_max_gc_sec(current_time); 75 return (jlong) (when * 1000.0); 76 } 77 78 inline jlong when_ms(double current_time, double pause_time) { 79 double when = when_sec(current_time, pause_time); 80 return (jlong) (when * 1000.0); 81 } 82 }; 83 84 class G1MMUTrackerQueueElem { 85 private: 86 double _start_time; 87 double _end_time; 88 89 public: 90 inline double start_time() { return _start_time; } 91 inline double end_time() { return _end_time; } 92 inline double duration() { return _end_time - _start_time; } 93 94 G1MMUTrackerQueueElem() { 95 _start_time = 0.0; 96 _end_time = 0.0; 97 } 98 99 G1MMUTrackerQueueElem(double start_time, double end_time) { 100 _start_time = start_time; 101 _end_time = end_time; 102 } 103 }; 104 105 // this is an implementation of the MMUTracker using a (fixed-size) queue 106 // that keeps track of all the recent pause times 107 class G1MMUTrackerQueue: public G1MMUTracker { 108 private: 109 enum PrivateConstants { 110 QueueLength = 64 111 }; 112 113 // The array keeps track of all the pauses that fall within a time 114 // slice (the last time slice during which pauses took place). 115 // The data structure implemented is a circular queue. 116 // Head "points" to the most recent addition, tail to the oldest one. 117 // The array is of fixed size and I don't think we'll need more than 118 // two or three entries with the current behavior of G1 pauses. 119 // If the array is full, an easy fix is to look for the pauses with 120 // the shortest gap between them and consolidate them. 121 // For now, we have taken the expedient alternative of forgetting 122 // the oldest entry in the event that +G1UseFixedWindowMMUTracker, thus 123 // potentially violating MMU specs for some time thereafter. 124 125 G1MMUTrackerQueueElem _array[QueueLength]; 126 int _head_index; 127 int _tail_index; 128 int _no_entries; 129 130 inline int trim_index(int index) { 131 return (index + QueueLength) % QueueLength; 132 } 133 134 void remove_expired_entries(double current_time); 135 double calculate_gc_time(double current_time); 136 137 public: 138 G1MMUTrackerQueue(double time_slice, double max_gc_time); 139 140 virtual void add_pause(double start, double end); 141 142 virtual double when_sec(double current_time, double pause_time); 143 }; 144 145 #endif // SHARE_VM_GC_G1_G1MMUTRACKER_HPP