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