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