| 1 | /* |
| 2 | * Copyright (c) 2011, 2019, 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 | #include "precompiled.hpp" |
| 26 | #include "gc/g1/g1CollectedHeap.inline.hpp" |
| 27 | #include "gc/g1/g1MonitoringSupport.hpp" |
| 28 | #include "gc/g1/g1Policy.hpp" |
| 29 | #include "gc/g1/g1MemoryPool.hpp" |
| 30 | #include "gc/shared/hSpaceCounters.hpp" |
| 31 | #include "memory/metaspaceCounters.hpp" |
| 32 | #include "services/memoryPool.hpp" |
| 33 | |
| 34 | class G1GenerationCounters : public GenerationCounters { |
| 35 | protected: |
| 36 | G1MonitoringSupport* _g1mm; |
| 37 | |
| 38 | public: |
| 39 | G1GenerationCounters(G1MonitoringSupport* g1mm, |
| 40 | const char* name, int ordinal, int spaces, |
| 41 | size_t min_capacity, size_t max_capacity, |
| 42 | size_t curr_capacity) |
| 43 | : GenerationCounters(name, ordinal, spaces, min_capacity, |
| 44 | max_capacity, curr_capacity), _g1mm(g1mm) { } |
| 45 | }; |
| 46 | |
| 47 | class G1YoungGenerationCounters : public G1GenerationCounters { |
| 48 | public: |
| 49 | // We pad the capacity three times given that the young generation |
| 50 | // contains three spaces (eden and two survivors). |
| 51 | G1YoungGenerationCounters(G1MonitoringSupport* g1mm, const char* name, size_t max_size) |
| 52 | : G1GenerationCounters(g1mm, name, 0 /* ordinal */, 3 /* spaces */, |
| 53 | G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */, |
| 54 | G1MonitoringSupport::pad_capacity(max_size, 3), |
| 55 | G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) { |
| 56 | if (UsePerfData) { |
| 57 | update_all(); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | virtual void update_all() { |
| 62 | size_t committed = |
| 63 | G1MonitoringSupport::pad_capacity(_g1mm->young_gen_committed(), 3); |
| 64 | _current_size->set_value(committed); |
| 65 | } |
| 66 | }; |
| 67 | |
| 68 | class G1OldGenerationCounters : public G1GenerationCounters { |
| 69 | public: |
| 70 | G1OldGenerationCounters(G1MonitoringSupport* g1mm, const char* name, size_t max_size) |
| 71 | : G1GenerationCounters(g1mm, name, 1 /* ordinal */, 1 /* spaces */, |
| 72 | G1MonitoringSupport::pad_capacity(0) /* min_capacity */, |
| 73 | G1MonitoringSupport::pad_capacity(max_size), |
| 74 | G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) { |
| 75 | if (UsePerfData) { |
| 76 | update_all(); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | virtual void update_all() { |
| 81 | size_t committed = |
| 82 | G1MonitoringSupport::pad_capacity(_g1mm->old_gen_committed()); |
| 83 | _current_size->set_value(committed); |
| 84 | } |
| 85 | }; |
| 86 | |
| 87 | G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : |
| 88 | _g1h(g1h), |
| 89 | _incremental_memory_manager("G1 Young Generation" , "end of minor GC" ), |
| 90 | _full_gc_memory_manager("G1 Old Generation" , "end of major GC" ), |
| 91 | _eden_space_pool(NULL), |
| 92 | _survivor_space_pool(NULL), |
| 93 | _old_gen_pool(NULL), |
| 94 | _incremental_collection_counters(NULL), |
| 95 | _full_collection_counters(NULL), |
| 96 | _conc_collection_counters(NULL), |
| 97 | _young_gen_counters(NULL), |
| 98 | _old_gen_counters(NULL), |
| 99 | _old_space_counters(NULL), |
| 100 | _eden_space_counters(NULL), |
| 101 | _from_space_counters(NULL), |
| 102 | _to_space_counters(NULL), |
| 103 | |
| 104 | _overall_committed(0), |
| 105 | _overall_used(0), |
| 106 | _young_gen_committed(0), |
| 107 | _old_gen_committed(0), |
| 108 | |
| 109 | _eden_space_committed(0), |
| 110 | _eden_space_used(0), |
| 111 | _survivor_space_committed(0), |
| 112 | _survivor_space_used(0), |
| 113 | _old_gen_used(0) { |
| 114 | |
| 115 | recalculate_sizes(); |
| 116 | |
| 117 | // Counters for garbage collections |
| 118 | // |
| 119 | // name "collector.0". In a generational collector this would be the |
| 120 | // young generation collection. |
| 121 | _incremental_collection_counters = |
| 122 | new CollectorCounters("G1 young collection pauses" , 0); |
| 123 | // name "collector.1". In a generational collector this would be the |
| 124 | // old generation collection. |
| 125 | _full_collection_counters = |
| 126 | new CollectorCounters("G1 full collection pauses" , 1); |
| 127 | // name "collector.2". In a generational collector this would be the |
| 128 | // STW phases in concurrent collection. |
| 129 | _conc_collection_counters = |
| 130 | new CollectorCounters("G1 concurrent cycle pauses" , 2); |
| 131 | |
| 132 | // "Generation" and "Space" counters. |
| 133 | // |
| 134 | // name "generation.1" This is logically the old generation in |
| 135 | // generational GC terms. The "1, 1" parameters are for |
| 136 | // the n-th generation (=1) with 1 space. |
| 137 | // Counters are created from minCapacity, maxCapacity, and capacity |
| 138 | _old_gen_counters = new G1OldGenerationCounters(this, "old" , _g1h->max_capacity()); |
| 139 | |
| 140 | // name "generation.1.space.0" |
| 141 | // Counters are created from maxCapacity, capacity, initCapacity, |
| 142 | // and used. |
| 143 | _old_space_counters = new HSpaceCounters(_old_gen_counters->name_space(), |
| 144 | "space" , 0 /* ordinal */, |
| 145 | pad_capacity(g1h->max_capacity()) /* max_capacity */, |
| 146 | pad_capacity(_old_gen_committed) /* init_capacity */); |
| 147 | |
| 148 | // Young collection set |
| 149 | // name "generation.0". This is logically the young generation. |
| 150 | // The "0, 3" are parameters for the n-th generation (=0) with 3 spaces. |
| 151 | // See _old_collection_counters for additional counters |
| 152 | _young_gen_counters = new G1YoungGenerationCounters(this, "young" , _g1h->max_capacity()); |
| 153 | |
| 154 | const char* young_collection_name_space = _young_gen_counters->name_space(); |
| 155 | |
| 156 | // name "generation.0.space.0" |
| 157 | // See _old_space_counters for additional counters |
| 158 | _eden_space_counters = new HSpaceCounters(young_collection_name_space, |
| 159 | "eden" , 0 /* ordinal */, |
| 160 | pad_capacity(g1h->max_capacity()) /* max_capacity */, |
| 161 | pad_capacity(_eden_space_committed) /* init_capacity */); |
| 162 | |
| 163 | // name "generation.0.space.1" |
| 164 | // See _old_space_counters for additional counters |
| 165 | // Set the arguments to indicate that this survivor space is not used. |
| 166 | _from_space_counters = new HSpaceCounters(young_collection_name_space, |
| 167 | "s0" , 1 /* ordinal */, |
| 168 | pad_capacity(0) /* max_capacity */, |
| 169 | pad_capacity(0) /* init_capacity */); |
| 170 | // Given that this survivor space is not used, we update it here |
| 171 | // once to reflect that its used space is 0 so that we don't have to |
| 172 | // worry about updating it again later. |
| 173 | if (UsePerfData) { |
| 174 | _from_space_counters->update_used(0); |
| 175 | } |
| 176 | |
| 177 | // name "generation.0.space.2" |
| 178 | // See _old_space_counters for additional counters |
| 179 | _to_space_counters = new HSpaceCounters(young_collection_name_space, |
| 180 | "s1" , 2 /* ordinal */, |
| 181 | pad_capacity(g1h->max_capacity()) /* max_capacity */, |
| 182 | pad_capacity(_survivor_space_committed) /* init_capacity */); |
| 183 | } |
| 184 | |
| 185 | G1MonitoringSupport::~G1MonitoringSupport() { |
| 186 | delete _eden_space_pool; |
| 187 | delete _survivor_space_pool; |
| 188 | delete _old_gen_pool; |
| 189 | } |
| 190 | |
| 191 | void G1MonitoringSupport::initialize_serviceability() { |
| 192 | _eden_space_pool = new G1EdenPool(_g1h, _eden_space_committed); |
| 193 | _survivor_space_pool = new G1SurvivorPool(_g1h, _survivor_space_committed); |
| 194 | _old_gen_pool = new G1OldGenPool(_g1h, _old_gen_committed, _g1h->max_capacity()); |
| 195 | |
| 196 | _full_gc_memory_manager.add_pool(_eden_space_pool); |
| 197 | _full_gc_memory_manager.add_pool(_survivor_space_pool); |
| 198 | _full_gc_memory_manager.add_pool(_old_gen_pool); |
| 199 | |
| 200 | _incremental_memory_manager.add_pool(_eden_space_pool); |
| 201 | _incremental_memory_manager.add_pool(_survivor_space_pool); |
| 202 | _incremental_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */); |
| 203 | } |
| 204 | |
| 205 | MemoryUsage G1MonitoringSupport::memory_usage() { |
| 206 | MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); |
| 207 | return MemoryUsage(InitialHeapSize, _overall_used, _overall_committed, _g1h->max_capacity()); |
| 208 | } |
| 209 | |
| 210 | GrowableArray<GCMemoryManager*> G1MonitoringSupport::memory_managers() { |
| 211 | GrowableArray<GCMemoryManager*> memory_managers(2); |
| 212 | memory_managers.append(&_incremental_memory_manager); |
| 213 | memory_managers.append(&_full_gc_memory_manager); |
| 214 | return memory_managers; |
| 215 | } |
| 216 | |
| 217 | GrowableArray<MemoryPool*> G1MonitoringSupport::memory_pools() { |
| 218 | GrowableArray<MemoryPool*> memory_pools(3); |
| 219 | memory_pools.append(_eden_space_pool); |
| 220 | memory_pools.append(_survivor_space_pool); |
| 221 | memory_pools.append(_old_gen_pool); |
| 222 | return memory_pools; |
| 223 | } |
| 224 | |
| 225 | void G1MonitoringSupport::recalculate_sizes() { |
| 226 | assert_heap_locked_or_at_safepoint(true); |
| 227 | |
| 228 | MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); |
| 229 | // Recalculate all the sizes from scratch. |
| 230 | |
| 231 | // This never includes used bytes of current allocating heap region. |
| 232 | _overall_used = _g1h->used_unlocked(); |
| 233 | _eden_space_used = _g1h->eden_regions_used_bytes(); |
| 234 | _survivor_space_used = _g1h->survivor_regions_used_bytes(); |
| 235 | |
| 236 | // _overall_used and _eden_space_used are obtained concurrently so |
| 237 | // may be inconsistent with each other. To prevent _old_gen_used going negative, |
| 238 | // use smaller value to substract. |
| 239 | _old_gen_used = _overall_used - MIN2(_overall_used, _eden_space_used + _survivor_space_used); |
| 240 | |
| 241 | uint survivor_list_length = _g1h->survivor_regions_count(); |
| 242 | // Max length includes any potential extensions to the young gen |
| 243 | // we'll do when the GC locker is active. |
| 244 | uint young_list_max_length = _g1h->policy()->young_list_max_length(); |
| 245 | assert(young_list_max_length >= survivor_list_length, "invariant" ); |
| 246 | uint eden_list_max_length = young_list_max_length - survivor_list_length; |
| 247 | |
| 248 | // First calculate the committed sizes that can be calculated independently. |
| 249 | _survivor_space_committed = survivor_list_length * HeapRegion::GrainBytes; |
| 250 | _old_gen_committed = HeapRegion::align_up_to_region_byte_size(_old_gen_used); |
| 251 | |
| 252 | // Next, start with the overall committed size. |
| 253 | _overall_committed = _g1h->capacity(); |
| 254 | size_t committed = _overall_committed; |
| 255 | |
| 256 | // Remove the committed size we have calculated so far (for the |
| 257 | // survivor and old space). |
| 258 | assert(committed >= (_survivor_space_committed + _old_gen_committed), "sanity" ); |
| 259 | committed -= _survivor_space_committed + _old_gen_committed; |
| 260 | |
| 261 | // Next, calculate and remove the committed size for the eden. |
| 262 | _eden_space_committed = (size_t) eden_list_max_length * HeapRegion::GrainBytes; |
| 263 | // Somewhat defensive: be robust in case there are inaccuracies in |
| 264 | // the calculations |
| 265 | _eden_space_committed = MIN2(_eden_space_committed, committed); |
| 266 | committed -= _eden_space_committed; |
| 267 | |
| 268 | // Finally, give the rest to the old space... |
| 269 | _old_gen_committed += committed; |
| 270 | // ..and calculate the young gen committed. |
| 271 | _young_gen_committed = _eden_space_committed + _survivor_space_committed; |
| 272 | |
| 273 | assert(_overall_committed == |
| 274 | (_eden_space_committed + _survivor_space_committed + _old_gen_committed), |
| 275 | "the committed sizes should add up" ); |
| 276 | // Somewhat defensive: cap the eden used size to make sure it |
| 277 | // never exceeds the committed size. |
| 278 | _eden_space_used = MIN2(_eden_space_used, _eden_space_committed); |
| 279 | // _survivor_space_used is calculated during a safepoint and _survivor_space_committed |
| 280 | // is calculated from survivor region count * heap region size. |
| 281 | assert(_survivor_space_used <= _survivor_space_committed, "Survivor used bytes(" SIZE_FORMAT |
| 282 | ") should be less than or equal to survivor committed(" SIZE_FORMAT ")" , |
| 283 | _survivor_space_used, _survivor_space_committed); |
| 284 | // _old_gen_committed is calculated in terms of _old_gen_used value. |
| 285 | assert(_old_gen_used <= _old_gen_committed, "Old gen used bytes(" SIZE_FORMAT |
| 286 | ") should be less than or equal to old gen committed(" SIZE_FORMAT ")" , |
| 287 | _old_gen_used, _old_gen_committed); |
| 288 | } |
| 289 | |
| 290 | void G1MonitoringSupport::update_sizes() { |
| 291 | recalculate_sizes(); |
| 292 | if (UsePerfData) { |
| 293 | _eden_space_counters->update_capacity(pad_capacity(_eden_space_committed)); |
| 294 | _eden_space_counters->update_used(_eden_space_used); |
| 295 | // only the "to" survivor space is active, so we don't need to |
| 296 | // update the counters for the "from" survivor space |
| 297 | _to_space_counters->update_capacity(pad_capacity(_survivor_space_committed)); |
| 298 | _to_space_counters->update_used(_survivor_space_used); |
| 299 | _old_space_counters->update_capacity(pad_capacity(_old_gen_committed)); |
| 300 | _old_space_counters->update_used(_old_gen_used); |
| 301 | |
| 302 | _young_gen_counters->update_all(); |
| 303 | _old_gen_counters->update_all(); |
| 304 | |
| 305 | MetaspaceCounters::update_performance_counters(); |
| 306 | CompressedClassSpaceCounters::update_performance_counters(); |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | void G1MonitoringSupport::update_eden_size() { |
| 311 | // Recalculate everything - this should be fast enough and we are sure that we do not |
| 312 | // miss anything. |
| 313 | recalculate_sizes(); |
| 314 | if (UsePerfData) { |
| 315 | _eden_space_counters->update_used(_eden_space_used); |
| 316 | } |
| 317 | } |
| 318 | |
| 319 | MemoryUsage G1MonitoringSupport::eden_space_memory_usage(size_t initial_size, size_t max_size) { |
| 320 | MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); |
| 321 | |
| 322 | return MemoryUsage(initial_size, |
| 323 | _eden_space_used, |
| 324 | _eden_space_committed, |
| 325 | max_size); |
| 326 | } |
| 327 | |
| 328 | MemoryUsage G1MonitoringSupport::survivor_space_memory_usage(size_t initial_size, size_t max_size) { |
| 329 | MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); |
| 330 | |
| 331 | return MemoryUsage(initial_size, |
| 332 | _survivor_space_used, |
| 333 | _survivor_space_committed, |
| 334 | max_size); |
| 335 | } |
| 336 | |
| 337 | MemoryUsage G1MonitoringSupport::old_gen_memory_usage(size_t initial_size, size_t max_size) { |
| 338 | MutexLocker x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); |
| 339 | |
| 340 | return MemoryUsage(initial_size, |
| 341 | _old_gen_used, |
| 342 | _old_gen_committed, |
| 343 | max_size); |
| 344 | } |
| 345 | |
| 346 | G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* g1mm, bool full_gc, bool all_memory_pools_affected) : |
| 347 | _tcs(full_gc ? g1mm->_full_collection_counters : g1mm->_incremental_collection_counters), |
| 348 | _tms(full_gc ? &g1mm->_full_gc_memory_manager : &g1mm->_incremental_memory_manager, |
| 349 | G1CollectedHeap::heap()->gc_cause(), all_memory_pools_affected) { |
| 350 | } |
| 351 | |