jmasa@2821: /* jmasa@2821: * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. jmasa@2821: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jmasa@2821: * jmasa@2821: * This code is free software; you can redistribute it and/or modify it jmasa@2821: * under the terms of the GNU General Public License version 2 only, as jmasa@2821: * published by the Free Software Foundation. jmasa@2821: * jmasa@2821: * This code is distributed in the hope that it will be useful, but WITHOUT jmasa@2821: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jmasa@2821: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jmasa@2821: * version 2 for more details (a copy is included in the LICENSE file that jmasa@2821: * accompanied this code). jmasa@2821: * jmasa@2821: * You should have received a copy of the GNU General Public License version jmasa@2821: * 2 along with this work; if not, write to the Free Software Foundation, jmasa@2821: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jmasa@2821: * jmasa@2821: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jmasa@2821: * or visit www.oracle.com if you need additional information or have any jmasa@2821: * questions. jmasa@2821: * jmasa@2821: */ jmasa@2821: jmasa@2821: #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP jmasa@2821: #define SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP jmasa@2821: jmasa@2821: #include "gc_implementation/shared/hSpaceCounters.hpp" jmasa@2821: jmasa@2821: class G1CollectedHeap; jmasa@2821: class G1SpaceMonitoringSupport; jmasa@2821: jmasa@2821: // Class for monitoring logical spaces in G1. jmasa@2821: // G1 defines a set of regions as a young jmasa@2821: // collection (analogous to a young generation). jmasa@2821: // The young collection is a logical generation jmasa@2821: // with no fixed chunk (see space.hpp) reflecting jmasa@2821: // the address space for the generation. In addition jmasa@2821: // to the young collection there is its complement jmasa@2821: // the non-young collection that is simply the regions jmasa@2821: // not in the young collection. The non-young collection jmasa@2821: // is treated here as a logical old generation only jmasa@2821: // because the monitoring tools expect a generational jmasa@2821: // heap. The monitoring tools expect that a Space jmasa@2821: // (see space.hpp) exists that describe the jmasa@2821: // address space of young collection and non-young jmasa@2821: // collection and such a view is provided here. jmasa@2821: // jmasa@2821: // This class provides interfaces to access jmasa@2821: // the value of variables for the young collection jmasa@2821: // that include the "capacity" and "used" of the jmasa@2821: // young collection along with constant values jmasa@2821: // for the minimum and maximum capacities for jmasa@2821: // the logical spaces. Similarly for the non-young jmasa@2821: // collection. jmasa@2821: // jmasa@2821: // Also provided are counters for G1 concurrent collections jmasa@2821: // and stop-the-world full heap collecitons. jmasa@2821: // jmasa@2821: // Below is a description of how "used" and "capactiy" jmasa@2821: // (or committed) is calculated for the logical spaces. jmasa@2821: // jmasa@2821: // 1) The used space calculation for a pool is not necessarily jmasa@2821: // independent of the others. We can easily get from G1 the overall jmasa@2821: // used space in the entire heap, the number of regions in the young jmasa@2821: // generation (includes both eden and survivors), and the number of jmasa@2821: // survivor regions. So, from that we calculate: jmasa@2821: // jmasa@2821: // survivor_used = survivor_num * region_size jmasa@2821: // eden_used = young_region_num * region_size - survivor_used jmasa@2821: // old_gen_used = overall_used - eden_used - survivor_used jmasa@2821: // jmasa@2821: // Note that survivor_used and eden_used are upper bounds. To get the jmasa@2821: // actual value we would have to iterate over the regions and add up jmasa@2821: // ->used(). But that'd be expensive. So, we'll accept some lack of jmasa@2821: // accuracy for those two. But, we have to be careful when calculating jmasa@2821: // old_gen_used, in case we subtract from overall_used more then the jmasa@2821: // actual number and our result goes negative. jmasa@2821: // jmasa@2821: // 2) Calculating the used space is straightforward, as described jmasa@2821: // above. However, how do we calculate the committed space, given that jmasa@2821: // we allocate space for the eden, survivor, and old gen out of the jmasa@2821: // same pool of regions? One way to do this is to use the used value jmasa@2821: // as also the committed value for the eden and survivor spaces and jmasa@2821: // then calculate the old gen committed space as follows: jmasa@2821: // jmasa@2821: // old_gen_committed = overall_committed - eden_committed - survivor_committed jmasa@2821: // jmasa@2821: // Maybe a better way to do that would be to calculate used for eden jmasa@2821: // and survivor as a sum of ->used() over their regions and then jmasa@2821: // calculate committed as region_num * region_size (i.e., what we use jmasa@2821: // to calculate the used space now). This is something to consider jmasa@2821: // in the future. jmasa@2821: // jmasa@2821: // 3) Another decision that is again not straightforward is what is jmasa@2821: // the max size that each memory pool can grow to. One way to do this jmasa@2821: // would be to use the committed size for the max for the eden and jmasa@2821: // survivors and calculate the old gen max as follows (basically, it's jmasa@2821: // a similar pattern to what we use for the committed space, as jmasa@2821: // described above): jmasa@2821: // jmasa@2821: // old_gen_max = overall_max - eden_max - survivor_max jmasa@2821: // jmasa@2821: // Unfortunately, the above makes the max of each pool fluctuate over jmasa@2821: // time and, even though this is allowed according to the spec, it jmasa@2821: // broke several assumptions in the M&M framework (there were cases jmasa@2821: // where used would reach a value greater than max). So, for max we jmasa@2821: // use -1, which means "undefined" according to the spec. jmasa@2821: // jmasa@2821: // 4) Now, there is a very subtle issue with all the above. The jmasa@2821: // framework will call get_memory_usage() on the three pools jmasa@2821: // asynchronously. As a result, each call might get a different value jmasa@2821: // for, say, survivor_num which will yield inconsistent values for jmasa@2821: // eden_used, survivor_used, and old_gen_used (as survivor_num is used jmasa@2821: // in the calculation of all three). This would normally be jmasa@2821: // ok. However, it's possible that this might cause the sum of jmasa@2821: // eden_used, survivor_used, and old_gen_used to go over the max heap jmasa@2821: // size and this seems to sometimes cause JConsole (and maybe other jmasa@2821: // clients) to get confused. There's not a really an easy / clean jmasa@2821: // solution to this problem, due to the asynchrounous nature of the jmasa@2821: // framework. jmasa@2821: jmasa@2821: class G1MonitoringSupport : public CHeapObj { jmasa@2821: G1CollectedHeap* _g1h; jmasa@2821: VirtualSpace* _g1_storage_addr; jmasa@2821: jmasa@2821: // jstat performance counters jmasa@2821: // incremental collections both fully and partially young jmasa@2821: CollectorCounters* _incremental_collection_counters; jmasa@2821: // full stop-the-world collections jmasa@2821: CollectorCounters* _full_collection_counters; jmasa@2821: // young collection set counters. The _eden_counters, jmasa@2821: // _from_counters, and _to_counters are associated with jmasa@2821: // this "generational" counter. jmasa@2821: GenerationCounters* _young_collection_counters; jmasa@2821: // non-young collection set counters. The _old_space_counters jmasa@2821: // below are associated with this "generational" counter. jmasa@2821: GenerationCounters* _non_young_collection_counters; jmasa@2821: // Counters for the capacity and used for jmasa@2821: // the whole heap jmasa@2821: HSpaceCounters* _old_space_counters; jmasa@2821: // the young collection jmasa@2821: HSpaceCounters* _eden_counters; jmasa@2821: // the survivor collection (only one, _to_counters, is actively used) jmasa@2821: HSpaceCounters* _from_counters; jmasa@2821: HSpaceCounters* _to_counters; jmasa@2821: jmasa@2821: // It returns x - y if x > y, 0 otherwise. jmasa@2821: // As described in the comment above, some of the inputs to the jmasa@2821: // calculations we have to do are obtained concurrently and hence jmasa@2821: // may be inconsistent with each other. So, this provides a jmasa@2821: // defensive way of performing the subtraction and avoids the value jmasa@2821: // going negative (which would mean a very large result, given that jmasa@2821: // the parameter are size_t). jmasa@2821: static size_t subtract_up_to_zero(size_t x, size_t y) { jmasa@2821: if (x > y) { jmasa@2821: return x - y; jmasa@2821: } else { jmasa@2821: return 0; jmasa@2821: } jmasa@2821: } jmasa@2821: jmasa@2821: public: jmasa@2821: G1MonitoringSupport(G1CollectedHeap* g1h, VirtualSpace* g1_storage_addr); jmasa@2821: jmasa@2821: G1CollectedHeap* g1h() { return _g1h; } jmasa@2821: VirtualSpace* g1_storage_addr() { return _g1_storage_addr; } jmasa@2821: jmasa@2821: // Performance Counter accessors jmasa@2821: void update_counters(); jmasa@2821: void update_eden_counters(); jmasa@2821: jmasa@2821: CollectorCounters* incremental_collection_counters() { jmasa@2821: return _incremental_collection_counters; jmasa@2821: } jmasa@2821: CollectorCounters* full_collection_counters() { jmasa@2821: return _full_collection_counters; jmasa@2821: } jmasa@2821: GenerationCounters* non_young_collection_counters() { jmasa@2821: return _non_young_collection_counters; jmasa@2821: } jmasa@2821: HSpaceCounters* old_space_counters() { return _old_space_counters; } jmasa@2821: HSpaceCounters* eden_counters() { return _eden_counters; } jmasa@2821: HSpaceCounters* from_counters() { return _from_counters; } jmasa@2821: HSpaceCounters* to_counters() { return _to_counters; } jmasa@2821: jmasa@2821: // Monitoring support used by jmasa@2821: // MemoryService jmasa@2821: // jstat counters jmasa@2821: size_t overall_committed(); jmasa@2821: size_t overall_used(); jmasa@2821: jmasa@2821: size_t eden_space_committed(); jmasa@2821: size_t eden_space_used(); jmasa@2821: jmasa@2821: size_t survivor_space_committed(); jmasa@2821: size_t survivor_space_used(); jmasa@2821: jmasa@2821: size_t old_space_committed(); jmasa@2821: size_t old_space_used(); jmasa@2821: }; jmasa@2821: jmasa@2821: #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP