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