1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018, SAP and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 #include "precompiled.hpp" 26 27 #include "memory/metachunk.hpp" 28 #include "memory/metaspace/metaspaceCommon.hpp" 29 #include "memory/metaspace/metaspaceStatistics.hpp" 30 #include "utilities/debug.hpp" 31 #include "utilities/globalDefinitions.hpp" 32 #include "utilities/ostream.hpp" 33 34 namespace metaspace { 35 namespace internals { 36 37 // FreeChunksStatistics methods 38 39 FreeChunksStatistics::FreeChunksStatistics() 40 : _num(0), _cap(0) 41 {} 42 43 void FreeChunksStatistics::reset() { 44 _num = 0; _cap = 0; 45 } 46 47 void FreeChunksStatistics::add(uintx n, size_t s) { 48 _num += n; _cap += s; 49 } 50 51 void FreeChunksStatistics::add(const FreeChunksStatistics& other) { 52 _num += other._num; 53 _cap += other._cap; 54 } 55 56 void FreeChunksStatistics::print_on(outputStream* st, size_t scale) const { 57 st->print(UINTX_FORMAT, _num); 58 st->print(" chunks, total capacity "); 59 print_scaled_words(st, _cap, scale); 60 } 61 62 // ChunkManagerStatistics methods 63 64 void ChunkManagerStatistics::reset() { 65 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { 66 _chunk_stats[i].reset(); 67 } 68 } 69 70 size_t ChunkManagerStatistics::total_capacity() const { 71 return _chunk_stats[SpecializedIndex].cap() + 72 _chunk_stats[SmallIndex].cap() + 73 _chunk_stats[MediumIndex].cap() + 74 _chunk_stats[HumongousIndex].cap(); 75 } 76 77 void ChunkManagerStatistics::print_on(outputStream* st, size_t scale) const { 78 FreeChunksStatistics totals; 79 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { 80 st->cr(); 81 st->print("%12s chunks: ", chunk_size_name(i)); 82 if (_chunk_stats[i].num() > 0) { 83 st->print(UINTX_FORMAT_W(4) ", capacity ", _chunk_stats[i].num()); 84 print_scaled_words(st, _chunk_stats[i].cap(), scale); 85 } else { 86 st->print("(none)"); 87 } 88 totals.add(_chunk_stats[i]); 89 } 90 st->cr(); 91 st->print("%19s: " UINTX_FORMAT_W(4) ", capacity=", "Total", totals.num()); 92 print_scaled_words(st, totals.cap(), scale); 93 st->cr(); 94 } 95 96 // UsedChunksStatistics methods 97 98 UsedChunksStatistics::UsedChunksStatistics() 99 : _num(0), _cap(0), _used(0), _free(0), _waste(0), _overhead(0) 100 {} 101 102 void UsedChunksStatistics::reset() { 103 _num = 0; 104 _cap = _overhead = _used = _free = _waste = 0; 105 } 106 107 void UsedChunksStatistics::add(const UsedChunksStatistics& other) { 108 _num += other._num; 109 _cap += other._cap; 110 _used += other._used; 111 _free += other._free; 112 _waste += other._waste; 113 _overhead += other._overhead; 114 DEBUG_ONLY(check_sanity()); 115 } 116 117 void UsedChunksStatistics::print_on(outputStream* st, size_t scale) const { 118 int col = st->position(); 119 st->print(UINTX_FORMAT_W(4) " chunk%s, ", _num, _num != 1 ? "s" : ""); 120 if (_num > 0) { 121 col += 14; st->fill_to(col); 122 123 print_scaled_words(st, _cap, scale, 5); 124 st->print(" capacity, "); 125 126 col += 18; st->fill_to(col); 127 print_scaled_words_and_percentage(st, _used, _cap, scale, 5); 128 st->print(" used, "); 129 130 col += 20; st->fill_to(col); 131 print_scaled_words_and_percentage(st, _free, _cap, scale, 5); 132 st->print(" free, "); 133 134 col += 20; st->fill_to(col); 135 print_scaled_words_and_percentage(st, _waste, _cap, scale, 5); 136 st->print(" waste, "); 137 138 col += 20; st->fill_to(col); 139 print_scaled_words_and_percentage(st, _overhead, _cap, scale, 5); 140 st->print(" overhead"); 141 } 142 DEBUG_ONLY(check_sanity()); 143 } 144 145 #ifdef ASSERT 146 void UsedChunksStatistics::check_sanity() const { 147 assert(_overhead == (Metachunk::overhead() * _num), "Sanity: Overhead."); 148 assert(_cap == _used + _free + _waste + _overhead, "Sanity: Capacity."); 149 } 150 #endif 151 152 // SpaceManagerStatistics methods 153 154 SpaceManagerStatistics::SpaceManagerStatistics() { reset(); } 155 156 void SpaceManagerStatistics::reset() { 157 for (int i = 0; i < NumberOfInUseLists; i ++) { 158 _chunk_stats[i].reset(); 159 _free_blocks_num = 0; _free_blocks_cap_words = 0; 160 } 161 } 162 163 void SpaceManagerStatistics::add_free_blocks_info(uintx num, size_t cap) { 164 _free_blocks_num += num; 165 _free_blocks_cap_words += cap; 166 } 167 168 void SpaceManagerStatistics::add(const SpaceManagerStatistics& other) { 169 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { 170 _chunk_stats[i].add(other._chunk_stats[i]); 171 } 172 _free_blocks_num += other._free_blocks_num; 173 _free_blocks_cap_words += other._free_blocks_cap_words; 174 } 175 176 // Returns total chunk statistics over all chunk types. 177 UsedChunksStatistics SpaceManagerStatistics::totals() const { 178 UsedChunksStatistics stat; 179 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { 180 stat.add(_chunk_stats[i]); 181 } 182 return stat; 183 } 184 185 void SpaceManagerStatistics::print_on(outputStream* st, size_t scale, bool detailed) const { 186 streamIndentor sti(st); 187 if (detailed) { 188 st->cr_indent(); 189 st->print("Usage by chunk type:"); 190 { 191 streamIndentor sti2(st); 192 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { 193 st->cr_indent(); 194 st->print("%15s: ", chunk_size_name(i)); 195 if (_chunk_stats[i].num() == 0) { 196 st->print(" (none)"); 197 } else { 198 _chunk_stats[i].print_on(st, scale); 199 } 200 } 201 202 st->cr_indent(); 203 st->print("%15s: ", "-total-"); 204 totals().print_on(st, scale); 205 } 206 if (_free_blocks_num > 0) { 207 st->cr_indent(); 208 st->print("deallocated: " UINTX_FORMAT " blocks with ", _free_blocks_num); 209 print_scaled_words(st, _free_blocks_cap_words, scale); 210 } 211 } else { 212 totals().print_on(st, scale); 213 st->print(", "); 214 st->print("deallocated: " UINTX_FORMAT " blocks with ", _free_blocks_num); 215 print_scaled_words(st, _free_blocks_cap_words, scale); 216 } 217 } 218 219 // ClassLoaderMetaspaceStatistics methods 220 221 ClassLoaderMetaspaceStatistics::ClassLoaderMetaspaceStatistics() { reset(); } 222 223 void ClassLoaderMetaspaceStatistics::reset() { 224 nonclass_sm_stats().reset(); 225 if (Metaspace::using_class_space()) { 226 class_sm_stats().reset(); 227 } 228 } 229 230 // Returns total space manager statistics for both class and non-class metaspace 231 SpaceManagerStatistics ClassLoaderMetaspaceStatistics::totals() const { 232 SpaceManagerStatistics stats; 233 stats.add(nonclass_sm_stats()); 234 if (Metaspace::using_class_space()) { 235 stats.add(class_sm_stats()); 236 } 237 return stats; 238 } 239 240 void ClassLoaderMetaspaceStatistics::add(const ClassLoaderMetaspaceStatistics& other) { 241 nonclass_sm_stats().add(other.nonclass_sm_stats()); 242 if (Metaspace::using_class_space()) { 243 class_sm_stats().add(other.class_sm_stats()); 244 } 245 } 246 247 void ClassLoaderMetaspaceStatistics::print_on(outputStream* st, size_t scale, bool detailed) const { 248 streamIndentor sti(st); 249 st->cr_indent(); 250 if (Metaspace::using_class_space()) { 251 st->print("Non-Class: "); 252 } 253 nonclass_sm_stats().print_on(st, scale, detailed); 254 if (detailed) { 255 st->cr(); 256 } 257 if (Metaspace::using_class_space()) { 258 st->cr_indent(); 259 st->print(" Class: "); 260 class_sm_stats().print_on(st, scale, detailed); 261 if (detailed) { 262 st->cr(); 263 } 264 st->cr_indent(); 265 st->print(" Both: "); 266 totals().print_on(st, scale, detailed); 267 if (detailed) { 268 st->cr(); 269 } 270 } 271 st->cr(); 272 } 273 274 275 } // end namespace internals 276 } // end namespace metaspace 277 278