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