1 /* 2 * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018, 2020 SAP SE. 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 26 #include "precompiled.hpp" 27 #include "cds/cdsConfig.hpp" 28 #include "classfile/classLoaderData.hpp" 29 #include "classfile/classLoaderDataGraph.hpp" 30 #include "memory/metaspace.hpp" 31 #include "memory/metaspace/chunkHeaderPool.hpp" 32 #include "memory/metaspace/chunkManager.hpp" 33 #include "memory/metaspace/internalStats.hpp" 34 #include "memory/metaspace/metaspaceCommon.hpp" 35 #include "memory/metaspace/metaspaceReporter.hpp" 36 #include "memory/metaspace/metaspaceSettings.hpp" 37 #include "memory/metaspace/metaspaceStatistics.hpp" 38 #include "memory/metaspace/printCLDMetaspaceInfoClosure.hpp" 39 #include "memory/metaspace/runningCounters.hpp" 40 #include "memory/metaspace/virtualSpaceList.hpp" 41 #include "memory/metaspaceUtils.hpp" 42 #include "runtime/os.hpp" 43 44 namespace metaspace { 45 46 static const char* describe_spacetype(Metaspace::MetaspaceType st) { 47 const char* s = nullptr; 48 switch (st) { 49 case Metaspace::StandardMetaspaceType: s = "Standard"; break; 50 case Metaspace::BootMetaspaceType: s = "Boot"; break; 51 case Metaspace::ClassMirrorHolderMetaspaceType: s = "ClassMirrorHolder"; break; 52 case Metaspace::ReflectionMetaspaceType: s = "Reflection"; break; 53 default: ShouldNotReachHere(); 54 } 55 return s; 56 } 57 58 static void print_vs(outputStream* out, size_t scale) { 59 const size_t reserved_nc = RunningCounters::reserved_words_nonclass(); 60 const size_t committed_nc = RunningCounters::committed_words_nonclass(); 61 const int num_nodes_nc = VirtualSpaceList::vslist_nonclass()->num_nodes(); 62 63 if (Metaspace::using_class_space()) { 64 const size_t reserved_c = RunningCounters::reserved_words_class(); 65 const size_t committed_c = RunningCounters::committed_words_class(); 66 const int num_nodes_c = VirtualSpaceList::vslist_class()->num_nodes(); 67 68 out->print(" Non-class space: "); 69 print_scaled_words(out, reserved_nc, scale, 7); 70 out->print(" reserved, "); 71 print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7); 72 out->print(" committed, "); 73 out->print(" %d nodes.", num_nodes_nc); 74 out->cr(); 75 out->print(" Class space: "); 76 print_scaled_words(out, reserved_c, scale, 7); 77 out->print(" reserved, "); 78 print_scaled_words_and_percentage(out, committed_c, reserved_c, scale, 7); 79 out->print(" committed, "); 80 out->print(" %d nodes.", num_nodes_c); 81 out->cr(); 82 out->print(" Both: "); 83 print_scaled_words(out, reserved_c + reserved_nc, scale, 7); 84 out->print(" reserved, "); 85 print_scaled_words_and_percentage(out, committed_c + committed_nc, reserved_c + reserved_nc, scale, 7); 86 out->print(" committed. "); 87 out->cr(); 88 } else { 89 print_scaled_words(out, reserved_nc, scale, 7); 90 out->print(" reserved, "); 91 print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7); 92 out->print(" committed, "); 93 out->print(" %d nodes.", num_nodes_nc); 94 out->cr(); 95 } 96 } 97 98 static void print_settings(outputStream* out, size_t scale) { 99 out->print("MaxMetaspaceSize: "); 100 if (MaxMetaspaceSize == max_uintx) { 101 out->print("unlimited"); 102 } else { 103 print_human_readable_size(out, MaxMetaspaceSize, scale); 104 } 105 out->cr(); 106 if (Metaspace::using_class_space()) { 107 out->print("CompressedClassSpaceSize: "); 108 print_human_readable_size(out, CompressedClassSpaceSize, scale); 109 } else { 110 out->print("No class space"); 111 } 112 out->cr(); 113 out->print("Initial GC threshold: "); 114 print_human_readable_size(out, MetaspaceSize, scale); 115 out->cr(); 116 out->print("Current GC threshold: "); 117 print_human_readable_size(out, MetaspaceGC::capacity_until_GC(), scale); 118 out->cr(); 119 out->print_cr("CDS: %s", (CDSConfig::is_using_archive() ? "on" : (CDSConfig::is_dumping_static_archive() ? "dump" : "off"))); 120 Settings::print_on(out); 121 } 122 123 // This will print out a basic metaspace usage report but 124 // unlike print_report() is guaranteed not to lock or to walk the CLDG. 125 void MetaspaceReporter::print_basic_report(outputStream* out, size_t scale) { 126 if (!Metaspace::initialized()) { 127 out->print_cr("Metaspace not yet initialized."); 128 return; 129 } 130 out->cr(); 131 out->print_cr("Usage:"); 132 if (Metaspace::using_class_space()) { 133 out->print(" Non-class: "); 134 } 135 136 // Note: since we want to purely rely on counters, without any locking or walking the CLDG, 137 // for Usage stats (statistics over in-use chunks) all we can print is the 138 // used words. We cannot print committed areas, or free/waste areas, of in-use chunks require 139 // walking. 140 const size_t used_nc = MetaspaceUtils::used_words(Metaspace::NonClassType); 141 142 print_scaled_words(out, used_nc, scale, 5); 143 out->print(" used."); 144 out->cr(); 145 if (Metaspace::using_class_space()) { 146 const size_t used_c = MetaspaceUtils::used_words(Metaspace::ClassType); 147 out->print(" Class: "); 148 print_scaled_words(out, used_c, scale, 5); 149 out->print(" used."); 150 out->cr(); 151 out->print(" Both: "); 152 const size_t used = used_nc + used_c; 153 print_scaled_words(out, used, scale, 5); 154 out->print(" used."); 155 out->cr(); 156 } 157 out->cr(); 158 out->print_cr("Virtual space:"); 159 print_vs(out, scale); 160 out->cr(); 161 out->print_cr("Chunk freelists:"); 162 if (Metaspace::using_class_space()) { 163 out->print(" Non-Class: "); 164 } 165 print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size(), scale); 166 out->cr(); 167 if (Metaspace::using_class_space()) { 168 out->print(" Class: "); 169 print_scaled_words(out, ChunkManager::chunkmanager_class()->total_word_size(), scale); 170 out->cr(); 171 out->print(" Both: "); 172 print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size() + 173 ChunkManager::chunkmanager_class()->total_word_size(), scale); 174 out->cr(); 175 } 176 out->cr(); 177 178 // Print basic settings 179 print_settings(out, scale); 180 out->cr(); 181 out->cr(); 182 out->print_cr("Internal statistics:"); 183 out->cr(); 184 InternalStats::print_on(out); 185 out->cr(); 186 } 187 188 void MetaspaceReporter::print_report(outputStream* out, size_t scale, int flags) { 189 if (!Metaspace::initialized()) { 190 out->print_cr("Metaspace not yet initialized."); 191 return; 192 } 193 const bool print_loaders = (flags & (int)Option::ShowLoaders) > 0; 194 const bool print_classes = (flags & (int)Option::ShowClasses) > 0; 195 const bool print_by_chunktype = (flags & (int)Option::BreakDownByChunkType) > 0; 196 const bool print_by_spacetype = (flags & (int)Option::BreakDownBySpaceType) > 0; 197 198 // Some report options require walking the class loader data graph. 199 metaspace::PrintCLDMetaspaceInfoClosure cl(out, scale, print_loaders, print_classes, print_by_chunktype); 200 if (print_loaders) { 201 out->cr(); 202 out->print_cr("Usage per loader:"); 203 out->cr(); 204 } 205 206 ClassLoaderDataGraph::loaded_cld_do(&cl); // collect data and optionally print 207 208 // Print totals, broken up by space type. 209 if (print_by_spacetype) { 210 out->cr(); 211 out->print_cr("Usage per space type:"); 212 out->cr(); 213 for (int space_type = (int)Metaspace::ZeroMetaspaceType; 214 space_type < (int)Metaspace::MetaspaceTypeCount; space_type++) 215 { 216 uintx num_loaders = cl._num_loaders_by_spacetype[space_type]; 217 uintx num_classes = cl._num_classes_by_spacetype[space_type]; 218 out->print("%s - " UINTX_FORMAT " %s", 219 describe_spacetype((Metaspace::MetaspaceType)space_type), 220 num_loaders, loaders_plural(num_loaders)); 221 if (num_classes > 0) { 222 out->print(", "); 223 224 print_number_of_classes(out, num_classes, cl._num_classes_shared_by_spacetype[space_type]); 225 out->print(":"); 226 cl._stats_by_spacetype[space_type].print_on(out, scale, print_by_chunktype); 227 } else { 228 out->print("."); 229 out->cr(); 230 } 231 out->cr(); 232 } 233 } 234 235 // Print totals for in-use data: 236 out->cr(); 237 { 238 uintx num_loaders = cl._num_loaders; 239 out->print("Total Usage - " UINTX_FORMAT " %s, ", 240 num_loaders, loaders_plural(num_loaders)); 241 print_number_of_classes(out, cl._num_classes, cl._num_classes_shared); 242 out->print(":"); 243 cl._stats_total.print_on(out, scale, print_by_chunktype); 244 out->cr(); 245 } 246 247 ///////////////////////////////////////////////// 248 // -- Print Virtual space. 249 out->cr(); 250 out->print_cr("Virtual space:"); 251 252 print_vs(out, scale); 253 254 // -- Print VirtualSpaceList details. 255 if ((flags & (int)Option::ShowVSList) > 0) { 256 out->cr(); 257 out->print_cr("Virtual space list%s:", Metaspace::using_class_space() ? "s" : ""); 258 259 if (Metaspace::using_class_space()) { 260 out->print_cr(" Non-Class:"); 261 } 262 VirtualSpaceList::vslist_nonclass()->print_on(out); 263 out->cr(); 264 if (Metaspace::using_class_space()) { 265 out->print_cr(" Class:"); 266 VirtualSpaceList::vslist_class()->print_on(out); 267 out->cr(); 268 } 269 } 270 out->cr(); 271 272 //////////// Freelists (ChunkManager) section /////////////////////////// 273 274 out->cr(); 275 out->print_cr("Chunk freelist%s:", Metaspace::using_class_space() ? "s" : ""); 276 277 ChunkManagerStats non_class_cm_stat; 278 ChunkManagerStats class_cm_stat; 279 ChunkManagerStats total_cm_stat; 280 281 ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat); 282 if (Metaspace::using_class_space()) { 283 ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat); 284 ChunkManager::chunkmanager_class()->add_to_statistics(&class_cm_stat); 285 total_cm_stat.add(non_class_cm_stat); 286 total_cm_stat.add(class_cm_stat); 287 288 out->print_cr(" Non-Class:"); 289 non_class_cm_stat.print_on(out, scale); 290 out->cr(); 291 out->print_cr(" Class:"); 292 class_cm_stat.print_on(out, scale); 293 out->cr(); 294 out->print_cr(" Both:"); 295 total_cm_stat.print_on(out, scale); 296 out->cr(); 297 } else { 298 ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat); 299 non_class_cm_stat.print_on(out, scale); 300 out->cr(); 301 } 302 303 // -- Print Chunkmanager details. 304 if ((flags & (int)Option::ShowChunkFreeList) > 0) { 305 out->cr(); 306 out->print_cr("Chunk freelist details:"); 307 if (Metaspace::using_class_space()) { 308 out->print_cr(" Non-Class:"); 309 } 310 ChunkManager::chunkmanager_nonclass()->print_on(out); 311 out->cr(); 312 if (Metaspace::using_class_space()) { 313 out->print_cr(" Class:"); 314 ChunkManager::chunkmanager_class()->print_on(out); 315 out->cr(); 316 } 317 } 318 out->cr(); 319 320 321 //////////// Waste section /////////////////////////// 322 // As a convenience, print a summary of common waste. 323 out->cr(); 324 out->print("Waste (unused committed space):"); 325 // For all wastages, print percentages from total. As total use the total size of memory committed for metaspace. 326 const size_t committed_words = RunningCounters::committed_words(); 327 328 out->print("(percentages refer to total committed size "); 329 print_scaled_words(out, committed_words, scale); 330 out->print_cr("):"); 331 332 // Print waste for in-use chunks. 333 InUseChunkStats ucs_nonclass = cl._stats_total._arena_stats_nonclass.totals(); 334 InUseChunkStats ucs_class = cl._stats_total._arena_stats_class.totals(); 335 const size_t waste_in_chunks_in_use = ucs_nonclass._waste_words + ucs_class._waste_words; 336 const size_t free_in_chunks_in_use = ucs_nonclass._free_words + ucs_class._free_words; 337 338 out->print(" Waste in chunks in use: "); 339 print_scaled_words_and_percentage(out, waste_in_chunks_in_use, committed_words, scale, 6); 340 out->cr(); 341 out->print(" Free in chunks in use: "); 342 print_scaled_words_and_percentage(out, free_in_chunks_in_use, committed_words, scale, 6); 343 out->cr(); 344 345 // Print waste in free chunks. 346 const size_t committed_in_free_chunks = total_cm_stat.total_committed_word_size(); 347 out->print(" In free chunks: "); 348 print_scaled_words_and_percentage(out, committed_in_free_chunks, committed_words, scale, 6); 349 out->cr(); 350 351 // Print waste in deallocated blocks. 352 const uintx free_blocks_num = 353 cl._stats_total._arena_stats_nonclass._free_blocks_num + 354 cl._stats_total._arena_stats_class._free_blocks_num; 355 const size_t free_blocks_cap_words = 356 cl._stats_total._arena_stats_nonclass._free_blocks_word_size + 357 cl._stats_total._arena_stats_class._free_blocks_word_size; 358 out->print("Deallocated from chunks in use: "); 359 print_scaled_words_and_percentage(out, free_blocks_cap_words, committed_words, scale, 6); 360 out->print(" (" UINTX_FORMAT " blocks)", free_blocks_num); 361 out->cr(); 362 363 // Print total waste. 364 const size_t total_waste = 365 waste_in_chunks_in_use + 366 free_in_chunks_in_use + 367 committed_in_free_chunks + 368 free_blocks_cap_words; 369 out->print(" -total-: "); 370 print_scaled_words_and_percentage(out, total_waste, committed_words, scale, 6); 371 out->cr(); 372 373 // Also print chunk header pool size. 374 out->cr(); 375 out->print("chunk header pool: %u items, ", ChunkHeaderPool::pool()->used()); 376 print_scaled_words(out, ChunkHeaderPool::pool()->memory_footprint_words(), scale); 377 out->print("."); 378 out->cr(); 379 380 // Print internal statistics 381 out->cr(); 382 out->print_cr("Internal statistics:"); 383 out->cr(); 384 InternalStats::print_on(out); 385 out->cr(); 386 387 // Print some interesting settings 388 out->cr(); 389 out->print_cr("Settings:"); 390 print_settings(out, scale); 391 392 out->cr(); 393 out->cr(); 394 395 DEBUG_ONLY(MetaspaceUtils::verify();) 396 } // MetaspaceUtils::print_report() 397 398 } // namespace metaspace 399