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 // Keeps track of the GC work and decides when it is OK to do GC work 33 // and for how long so that the MMU invariants are maintained. 34 35 /***** ALL TIMES ARE IN SECS!!!!!!! *****/ 36 37 // this is the "interface" 38 class G1MMUTracker: public CHeapObj<mtGC> { 39 protected: 40 double _time_slice; 41 double _max_gc_time; // this is per time slice 42 43 public: 44 G1MMUTracker(double time_slice, double max_gc_time); 45 46 virtual void add_pause(double start, double end, const GCId& gcId) = 0; 47 virtual double when_sec(double current_time, double pause_time) = 0; 48 49 double max_gc_time() { 50 return _max_gc_time; 51 } 52 53 inline bool now_max_gc(double current_time) { 54 return when_sec(current_time, max_gc_time()) < 0.00001; 55 } 56 57 inline double when_max_gc_sec(double current_time) { 58 return when_sec(current_time, max_gc_time()); 59 } 60 61 inline jlong when_max_gc_ms(double current_time) { 62 double when = when_max_gc_sec(current_time); 63 return (jlong) (when * 1000.0); 64 } 65 66 inline jlong when_ms(double current_time, double pause_time) { 67 double when = when_sec(current_time, pause_time); 68 return (jlong) (when * 1000.0); 69 } 70 }; 71 72 class G1MMUTrackerQueueElem VALUE_OBJ_CLASS_SPEC { 73 private: 74 double _start_time; 75 double _end_time; 76 77 public: 78 inline double start_time() { return _start_time; } 79 inline double end_time() { return _end_time; } 80 inline double duration() { return _end_time - _start_time; } 81 82 G1MMUTrackerQueueElem() { 83 _start_time = 0.0; 84 _end_time = 0.0; 85 } 86 87 G1MMUTrackerQueueElem(double start_time, double end_time) { 88 _start_time = start_time; 89 _end_time = end_time; 90 } 91 }; 92 93 // this is an implementation of the MMUTracker using a (fixed-size) queue 94 // that keeps track of all the recent pause times 95 class G1MMUTrackerQueue: public G1MMUTracker { 96 private: 97 enum PrivateConstants { 98 QueueLength = 64 99 }; 100 101 // The array keeps track of all the pauses that fall within a time 102 // slice (the last time slice during which pauses took place). 103 // The data structure implemented is a circular queue. 104 // Head "points" to the most recent addition, tail to the oldest one. 105 // The array is of fixed size and I don't think we'll need more than 106 // two or three entries with the current behavior of G1 pauses. 107 // If the array is full, an easy fix is to look for the pauses with 108 // the shortest gap between them and consolidate them. 109 // For now, we have taken the expedient alternative of forgetting 110 // the oldest entry in the event that +G1UseFixedWindowMMUTracker, thus 111 // potentially violating MMU specs for some time thereafter. 112 113 G1MMUTrackerQueueElem _array[QueueLength]; 114 int _head_index; 115 int _tail_index; 116 int _no_entries; 117 118 inline int trim_index(int index) { 119 return (index + QueueLength) % QueueLength; 120 } 121 122 void remove_expired_entries(double current_time); 123 double calculate_gc_time(double current_time); 124 125 double when_internal(double current_time, double pause_time); 126 127 public: 128 G1MMUTrackerQueue(double time_slice, double max_gc_time); 129 130 virtual void add_pause(double start, double end, const GCId& gcId); 131 132 virtual double when_sec(double current_time, double pause_time); 133 }; 134 135 #endif // SHARE_VM_GC_G1_G1MMUTRACKER_HPP