1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp Thu Apr 21 10:23:44 2011 -0700 1.3 @@ -0,0 +1,203 @@ 1.4 +/* 1.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP 1.29 +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP 1.30 + 1.31 +#include "gc_implementation/shared/hSpaceCounters.hpp" 1.32 + 1.33 +class G1CollectedHeap; 1.34 +class G1SpaceMonitoringSupport; 1.35 + 1.36 +// Class for monitoring logical spaces in G1. 1.37 +// G1 defines a set of regions as a young 1.38 +// collection (analogous to a young generation). 1.39 +// The young collection is a logical generation 1.40 +// with no fixed chunk (see space.hpp) reflecting 1.41 +// the address space for the generation. In addition 1.42 +// to the young collection there is its complement 1.43 +// the non-young collection that is simply the regions 1.44 +// not in the young collection. The non-young collection 1.45 +// is treated here as a logical old generation only 1.46 +// because the monitoring tools expect a generational 1.47 +// heap. The monitoring tools expect that a Space 1.48 +// (see space.hpp) exists that describe the 1.49 +// address space of young collection and non-young 1.50 +// collection and such a view is provided here. 1.51 +// 1.52 +// This class provides interfaces to access 1.53 +// the value of variables for the young collection 1.54 +// that include the "capacity" and "used" of the 1.55 +// young collection along with constant values 1.56 +// for the minimum and maximum capacities for 1.57 +// the logical spaces. Similarly for the non-young 1.58 +// collection. 1.59 +// 1.60 +// Also provided are counters for G1 concurrent collections 1.61 +// and stop-the-world full heap collecitons. 1.62 +// 1.63 +// Below is a description of how "used" and "capactiy" 1.64 +// (or committed) is calculated for the logical spaces. 1.65 +// 1.66 +// 1) The used space calculation for a pool is not necessarily 1.67 +// independent of the others. We can easily get from G1 the overall 1.68 +// used space in the entire heap, the number of regions in the young 1.69 +// generation (includes both eden and survivors), and the number of 1.70 +// survivor regions. So, from that we calculate: 1.71 +// 1.72 +// survivor_used = survivor_num * region_size 1.73 +// eden_used = young_region_num * region_size - survivor_used 1.74 +// old_gen_used = overall_used - eden_used - survivor_used 1.75 +// 1.76 +// Note that survivor_used and eden_used are upper bounds. To get the 1.77 +// actual value we would have to iterate over the regions and add up 1.78 +// ->used(). But that'd be expensive. So, we'll accept some lack of 1.79 +// accuracy for those two. But, we have to be careful when calculating 1.80 +// old_gen_used, in case we subtract from overall_used more then the 1.81 +// actual number and our result goes negative. 1.82 +// 1.83 +// 2) Calculating the used space is straightforward, as described 1.84 +// above. However, how do we calculate the committed space, given that 1.85 +// we allocate space for the eden, survivor, and old gen out of the 1.86 +// same pool of regions? One way to do this is to use the used value 1.87 +// as also the committed value for the eden and survivor spaces and 1.88 +// then calculate the old gen committed space as follows: 1.89 +// 1.90 +// old_gen_committed = overall_committed - eden_committed - survivor_committed 1.91 +// 1.92 +// Maybe a better way to do that would be to calculate used for eden 1.93 +// and survivor as a sum of ->used() over their regions and then 1.94 +// calculate committed as region_num * region_size (i.e., what we use 1.95 +// to calculate the used space now). This is something to consider 1.96 +// in the future. 1.97 +// 1.98 +// 3) Another decision that is again not straightforward is what is 1.99 +// the max size that each memory pool can grow to. One way to do this 1.100 +// would be to use the committed size for the max for the eden and 1.101 +// survivors and calculate the old gen max as follows (basically, it's 1.102 +// a similar pattern to what we use for the committed space, as 1.103 +// described above): 1.104 +// 1.105 +// old_gen_max = overall_max - eden_max - survivor_max 1.106 +// 1.107 +// Unfortunately, the above makes the max of each pool fluctuate over 1.108 +// time and, even though this is allowed according to the spec, it 1.109 +// broke several assumptions in the M&M framework (there were cases 1.110 +// where used would reach a value greater than max). So, for max we 1.111 +// use -1, which means "undefined" according to the spec. 1.112 +// 1.113 +// 4) Now, there is a very subtle issue with all the above. The 1.114 +// framework will call get_memory_usage() on the three pools 1.115 +// asynchronously. As a result, each call might get a different value 1.116 +// for, say, survivor_num which will yield inconsistent values for 1.117 +// eden_used, survivor_used, and old_gen_used (as survivor_num is used 1.118 +// in the calculation of all three). This would normally be 1.119 +// ok. However, it's possible that this might cause the sum of 1.120 +// eden_used, survivor_used, and old_gen_used to go over the max heap 1.121 +// size and this seems to sometimes cause JConsole (and maybe other 1.122 +// clients) to get confused. There's not a really an easy / clean 1.123 +// solution to this problem, due to the asynchrounous nature of the 1.124 +// framework. 1.125 + 1.126 +class G1MonitoringSupport : public CHeapObj { 1.127 + G1CollectedHeap* _g1h; 1.128 + VirtualSpace* _g1_storage_addr; 1.129 + 1.130 + // jstat performance counters 1.131 + // incremental collections both fully and partially young 1.132 + CollectorCounters* _incremental_collection_counters; 1.133 + // full stop-the-world collections 1.134 + CollectorCounters* _full_collection_counters; 1.135 + // young collection set counters. The _eden_counters, 1.136 + // _from_counters, and _to_counters are associated with 1.137 + // this "generational" counter. 1.138 + GenerationCounters* _young_collection_counters; 1.139 + // non-young collection set counters. The _old_space_counters 1.140 + // below are associated with this "generational" counter. 1.141 + GenerationCounters* _non_young_collection_counters; 1.142 + // Counters for the capacity and used for 1.143 + // the whole heap 1.144 + HSpaceCounters* _old_space_counters; 1.145 + // the young collection 1.146 + HSpaceCounters* _eden_counters; 1.147 + // the survivor collection (only one, _to_counters, is actively used) 1.148 + HSpaceCounters* _from_counters; 1.149 + HSpaceCounters* _to_counters; 1.150 + 1.151 + // It returns x - y if x > y, 0 otherwise. 1.152 + // As described in the comment above, some of the inputs to the 1.153 + // calculations we have to do are obtained concurrently and hence 1.154 + // may be inconsistent with each other. So, this provides a 1.155 + // defensive way of performing the subtraction and avoids the value 1.156 + // going negative (which would mean a very large result, given that 1.157 + // the parameter are size_t). 1.158 + static size_t subtract_up_to_zero(size_t x, size_t y) { 1.159 + if (x > y) { 1.160 + return x - y; 1.161 + } else { 1.162 + return 0; 1.163 + } 1.164 + } 1.165 + 1.166 + public: 1.167 + G1MonitoringSupport(G1CollectedHeap* g1h, VirtualSpace* g1_storage_addr); 1.168 + 1.169 + G1CollectedHeap* g1h() { return _g1h; } 1.170 + VirtualSpace* g1_storage_addr() { return _g1_storage_addr; } 1.171 + 1.172 + // Performance Counter accessors 1.173 + void update_counters(); 1.174 + void update_eden_counters(); 1.175 + 1.176 + CollectorCounters* incremental_collection_counters() { 1.177 + return _incremental_collection_counters; 1.178 + } 1.179 + CollectorCounters* full_collection_counters() { 1.180 + return _full_collection_counters; 1.181 + } 1.182 + GenerationCounters* non_young_collection_counters() { 1.183 + return _non_young_collection_counters; 1.184 + } 1.185 + HSpaceCounters* old_space_counters() { return _old_space_counters; } 1.186 + HSpaceCounters* eden_counters() { return _eden_counters; } 1.187 + HSpaceCounters* from_counters() { return _from_counters; } 1.188 + HSpaceCounters* to_counters() { return _to_counters; } 1.189 + 1.190 + // Monitoring support used by 1.191 + // MemoryService 1.192 + // jstat counters 1.193 + size_t overall_committed(); 1.194 + size_t overall_used(); 1.195 + 1.196 + size_t eden_space_committed(); 1.197 + size_t eden_space_used(); 1.198 + 1.199 + size_t survivor_space_committed(); 1.200 + size_t survivor_space_used(); 1.201 + 1.202 + size_t old_space_committed(); 1.203 + size_t old_space_used(); 1.204 +}; 1.205 + 1.206 +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP