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