1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018, SAP and/or its affiliates.
   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 #include "classfile/classLoaderData.hpp"
  27 #include "classfile/classLoaderDataGraph.hpp"
  28 #include "memory/metaspace/chunkManager.hpp"
  29 #include "memory/metaspace/metaspaceCommon.hpp"
  30 #include "memory/metaspace/metaspaceEnums.hpp"
  31 #include "memory/metaspace/metaspaceReport.hpp"
  32 #include "memory/metaspace/metaspaceStatistics.hpp"
  33 #include "memory/metaspace/printCLDMetaspaceInfoClosure.hpp"
  34 #include "memory/metaspace/runningCounters.hpp"
  35 #include "memory/metaspace/virtualSpaceList.hpp"
  36 #include "memory/metaspace.hpp"
  37 #include "runtime/os.hpp"
  38 
  39 namespace metaspace {
  40 
  41 static void print_vs(outputStream* out, size_t scale) {
  42   const size_t reserved_nonclass_words = RunningCounters::reserved_words_nonclass();
  43   const size_t committed_nonclass_words = RunningCounters::committed_words_nonclass();
  44   {
  45     if (Metaspace::using_class_space()) {
  46       out->print("  Non-class space:  ");
  47     }
  48     print_scaled_words(out, reserved_nonclass_words, scale, 7);
  49     out->print(" reserved, ");
  50     print_scaled_words_and_percentage(out, committed_nonclass_words, reserved_nonclass_words, scale, 7);
  51     out->print_cr(" committed ");
  52 
  53     if (Metaspace::using_class_space()) {
  54       const size_t reserved_class_words = RunningCounters::reserved_words_class();
  55       const size_t committed_class_words = RunningCounters::committed_words_class();
  56       out->print("      Class space:  ");
  57       print_scaled_words(out, reserved_class_words, scale, 7);
  58       out->print(" reserved, ");
  59       print_scaled_words_and_percentage(out, committed_class_words, reserved_class_words, scale, 7);
  60       out->print_cr(" committed ");
  61 
  62       const size_t reserved_words = reserved_nonclass_words + reserved_class_words;
  63       const size_t committed_words = committed_nonclass_words + committed_class_words;
  64       out->print("             Both:  ");
  65       print_scaled_words(out, reserved_words, scale, 7);
  66       out->print(" reserved, ");
  67       print_scaled_words_and_percentage(out, committed_words, reserved_words, scale, 7);
  68       out->print_cr(" committed ");
  69     }
  70   }
  71 }
  72 
  73 static void print_basic_switches(outputStream* out, size_t scale) {
  74   out->print("MaxMetaspaceSize: ");
  75   if (MaxMetaspaceSize >= (max_uintx) - (2 * os::vm_page_size())) {
  76     // aka "very big". Default is max_uintx, but due to rounding in arg parsing the real
  77     // value is smaller.
  78     out->print("unlimited");
  79   } else {
  80     print_human_readable_size(out, MaxMetaspaceSize, scale);
  81   }
  82   out->cr();
  83   if (Metaspace::using_class_space()) {
  84     out->print("CompressedClassSpaceSize: ");
  85     print_human_readable_size(out, CompressedClassSpaceSize, scale);
  86   }
  87   out->cr();
  88 }
  89 
  90 // This will print out a basic metaspace usage report but
  91 // unlike print_report() is guaranteed not to lock or to walk the CLDG.
  92 void MetaspaceReporter::print_basic_report(outputStream* out, size_t scale) {
  93 /*
  94   if (!Metaspace::initialized()) {
  95     out->print_cr("Metaspace not yet initialized.");
  96     return;
  97   }
  98 
  99   out->cr();
 100   out->print_cr("Usage:");
 101 
 102   if (Metaspace::using_class_space()) {
 103     out->print("  Non-class:  ");
 104   }
 105 
 106   // In its most basic form, we do not require walking the CLDG. Instead, just print the running totals from
 107   // MetaspaceUtils.
 108   const size_t cap_nc = MetaspaceUtils::capacity_words(metaspace::NonClassType);
 109   const size_t overhead_nc = MetaspaceUtils::overhead_words(metaspace::NonClassType);
 110   const size_t used_nc = MetaspaceUtils::used_words(metaspace::NonClassType);
 111   const size_t free_and_waste_nc = cap_nc - overhead_nc - used_nc;
 112 
 113   print_scaled_words(out, cap_nc, scale, 5);
 114   out->print(" capacity, ");
 115   print_scaled_words_and_percentage(out, used_nc, cap_nc, scale, 5);
 116   out->print(" used, ");
 117   print_scaled_words_and_percentage(out, free_and_waste_nc, cap_nc, scale, 5);
 118   out->print(" free+waste, ");
 119   print_scaled_words_and_percentage(out, overhead_nc, cap_nc, scale, 5);
 120   out->print(" overhead. ");
 121   out->cr();
 122 
 123   if (Metaspace::using_class_space()) {
 124     const size_t cap_c = MetaspaceUtils::capacity_words(metaspace::ClassType);
 125     const size_t overhead_c = MetaspaceUtils::overhead_words(metaspace::ClassType);
 126     const size_t used_c = MetaspaceUtils::used_words(metaspace::ClassType);
 127     const size_t free_and_waste_c = cap_c - overhead_c - used_c;
 128     out->print("      Class:  ");
 129     print_scaled_words(out, cap_c, scale, 5);
 130     out->print(" capacity, ");
 131     print_scaled_words_and_percentage(out, used_c, cap_c, scale, 5);
 132     out->print(" used, ");
 133     print_scaled_words_and_percentage(out, free_and_waste_c, cap_c, scale, 5);
 134     out->print(" free+waste, ");
 135     print_scaled_words_and_percentage(out, overhead_c, cap_c, scale, 5);
 136     out->print(" overhead. ");
 137     out->cr();
 138 
 139     out->print("       Both:  ");
 140     const size_t cap = cap_nc + cap_c;
 141 
 142     print_scaled_words(out, cap, scale, 5);
 143     out->print(" capacity, ");
 144     print_scaled_words_and_percentage(out, used_nc + used_c, cap, scale, 5);
 145     out->print(" used, ");
 146     print_scaled_words_and_percentage(out, free_and_waste_nc + free_and_waste_c, cap, scale, 5);
 147     out->print(" free+waste, ");
 148     print_scaled_words_and_percentage(out, overhead_nc + overhead_c, cap, scale, 5);
 149     out->print(" overhead. ");
 150     out->cr();
 151   }
 152 
 153   out->cr();
 154   out->print_cr("Virtual space:");
 155 
 156   print_vs(out, scale);
 157 
 158   out->cr();
 159   out->print_cr("Chunk freelists:");
 160 
 161   if (Metaspace::using_class_space()) {
 162     out->print("   Non-Class:  ");
 163   }
 164   print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size(), scale);
 165   out->cr();
 166   if (Metaspace::using_class_space()) {
 167     out->print("       Class:  ");
 168     print_scaled_words(out, ChunkManager::chunkmanager_class()->total_word_size(), scale);
 169     out->cr();
 170     out->print("        Both:  ");
 171     print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size() +
 172                             ChunkManager::chunkmanager_class()->total_word_size(), scale);
 173     out->cr();
 174   }
 175 
 176   out->cr();
 177 
 178   // Print basic settings
 179   print_basic_switches(out, scale);
 180 
 181   out->cr();
 182 */
 183 }
 184 
 185 void MetaspaceReporter::print_report(outputStream* out, size_t scale, int flags) {
 186 
 187   if (!Metaspace::initialized()) {
 188     out->print_cr("Metaspace not yet initialized.");
 189     return;
 190   }
 191 
 192   const bool print_loaders = (flags & rf_show_loaders) > 0;
 193   const bool print_classes = (flags & rf_show_classes) > 0;
 194   const bool print_by_chunktype = (flags & rf_break_down_by_chunktype) > 0;
 195   const bool print_by_spacetype = (flags & rf_break_down_by_spacetype) > 0;
 196 
 197   // Some report options require walking the class loader data graph.
 198   metaspace::PrintCLDMetaspaceInfoClosure cl(out, scale, print_loaders, print_classes, print_by_chunktype);
 199   if (print_loaders) {
 200     out->cr();
 201     out->print_cr("Usage per loader:");
 202     out->cr();
 203   }
 204 
 205   ClassLoaderDataGraph::loaded_cld_do(&cl); // collect data and optionally print
 206 
 207   // Print totals, broken up by space type.
 208   if (print_by_spacetype) {
 209     out->cr();
 210     out->print_cr("Usage per space type:");
 211     out->cr();
 212     for (int space_type = (int)metaspace::ZeroMetaspaceType;
 213          space_type < (int)metaspace::MetaspaceTypeCount; space_type ++)
 214     {
 215       uintx num_loaders = cl._num_loaders_by_spacetype[space_type];
 216       uintx num_classes = cl._num_classes_by_spacetype[space_type];
 217       out->print("%s - " UINTX_FORMAT " %s",
 218         describe_spacetype((MetaspaceType)space_type),
 219         num_loaders, loaders_plural(num_loaders));
 220       if (num_classes > 0) {
 221         out->print(", ");
 222         print_number_of_classes(out, num_classes, cl._num_classes_shared_by_spacetype[space_type]);
 223         out->print(":");
 224         cl._stats_by_spacetype[space_type].print_on(out, scale, print_by_chunktype);
 225       } else {
 226         out->print(".");
 227         out->cr();
 228       }
 229       out->cr();
 230     }
 231   }
 232 
 233   // Print totals for in-use data:
 234   out->cr();
 235   {
 236     uintx num_loaders = cl._num_loaders;
 237     out->print("Total Usage - " UINTX_FORMAT " %s, ",
 238       num_loaders, loaders_plural(num_loaders));
 239     print_number_of_classes(out, cl._num_classes, cl._num_classes_shared);
 240     out->print(":");
 241     cl._stats_total.print_on(out, scale, print_by_chunktype);
 242     out->cr();
 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, scale);
 260     if (Metaspace::using_class_space()) {
 261       out->print_cr("       Class:");
 262       VirtualSpaceList::vslist_class()->print_on(out, scale);
 263     }
 264   }
 265   out->cr();
 266 
 267   // -- Print VirtualSpaceList map.
 268 /* Deactivated for now.
 269   if ((flags & rf_show_vsmap) > 0) {
 270     out->cr();
 271     out->print_cr("Virtual space map:");
 272 
 273     if (Metaspace::using_class_space()) {
 274       out->print_cr("   Non-Class:");
 275     }
 276     Metaspace::space_list()->print_map(out);
 277     if (Metaspace::using_class_space()) {
 278       out->print_cr("       Class:");
 279       Metaspace::class_space_list()->print_map(out);
 280     }
 281   }
 282   out->cr();
 283 */
 284 
 285   // -- Print Freelists (ChunkManager) details
 286   out->cr();
 287   out->print_cr("Chunk freelist%s:", Metaspace::using_class_space() ? "s" : "");
 288 
 289   ChunkManagerStatistics non_class_cm_stat;
 290   ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat);
 291 
 292   if (Metaspace::using_class_space()) {
 293     out->print_cr("   Non-Class:");
 294   }
 295   non_class_cm_stat.print_on(out, scale);
 296 
 297   if (Metaspace::using_class_space()) {
 298     ChunkManagerStatistics class_cm_stat;
 299     ChunkManager::chunkmanager_class()->add_to_statistics(&class_cm_stat);
 300     out->print_cr("       Class:");
 301     class_cm_stat.print_on(out, scale);
 302   }
 303 
 304   // As a convenience, print a summary of common waste.
 305   out->cr();
 306   out->print("Waste ");
 307   // For all wastages, print percentages from total. As total use the total size of memory committed for metaspace.
 308   const size_t committed_words = RunningCounters::committed_words();
 309 
 310   out->print("(percentages refer to total committed size ");
 311   print_scaled_words(out, committed_words, scale);
 312   out->print_cr("):");
 313 
 314   // Print space committed but not yet used by any class loader
 315   const size_t unused_words_in_vs = 0;// TODO MetaspaceUtils::free_in_vs_bytes() / BytesPerWord;
 316   out->print("              Committed unused: ");
 317   print_scaled_words_and_percentage(out, unused_words_in_vs, committed_words, scale, 6);
 318   out->cr();
 319 
 320   // Print waste for in-use chunks.
 321   UsedChunksStatistics ucs_nonclass = cl._stats_total.sm_stats[metaspace::NonClassType].totals();
 322   UsedChunksStatistics ucs_class = cl._stats_total.sm_stats[metaspace::ClassType].totals();
 323   UsedChunksStatistics ucs_all;
 324   ucs_all.add(ucs_nonclass);
 325   ucs_all.add(ucs_class);
 326 
 327   out->print("        Waste in chunks in use: ");
 328   print_scaled_words_and_percentage(out, ucs_all.waste, committed_words, scale, 6);
 329   out->cr();
 330   out->print("        Free (committed) in chunks in use: ");
 331   print_scaled_words_and_percentage(out, ucs_all.free, committed_words, scale, 6);
 332   out->cr();
 333 /*
 334   // Print waste in free chunks.
 335   const size_t total_capacity_in_free_chunks =
 336       Metaspace::chunk_manager_metadata()->free_chunks_total_words() +
 337      (Metaspace::using_class_space() ? Metaspace::chunk_manager_class()->free_chunks_total_words() : 0);
 338   out->print("                In free chunks: ");
 339   print_scaled_words_and_percentage(out, total_capacity_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.nonclass_sm_stats().free_blocks_num() +
 345       cl._stats_total.class_sm_stats().free_blocks_num();
 346   const size_t free_blocks_cap_words =
 347       cl._stats_total.nonclass_sm_stats().free_blocks_cap_words() +
 348       cl._stats_total.class_sm_stats().free_blocks_cap_words();
 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 = ucs_all.waste() + ucs_all.free() + ucs_all.overhead() + total_capacity_in_free_chunks
 356       + free_blocks_cap_words + unused_words_in_vs;
 357   out->print("                       -total-: ");
 358   print_scaled_words_and_percentage(out, total_waste, committed_words, scale, 6);
 359   out->cr();
 360 */
 361   // Print internal statistics
 362 #ifdef ASSERT
 363   out->cr();
 364   out->cr();
 365   out->print_cr("Internal statistics:");
 366   out->cr();
 367   out->print_cr("Number of allocations: " UINTX_FORMAT ".", g_internal_statistics.num_allocs);
 368   out->print_cr("Number of space births: " UINTX_FORMAT ".", g_internal_statistics.num_metaspace_births);
 369   out->print_cr("Number of space deaths: " UINTX_FORMAT ".", g_internal_statistics.num_metaspace_deaths);
 370   out->print_cr("Number of virtual space node births: " UINTX_FORMAT ".", g_internal_statistics.num_vsnodes_created);
 371   out->print_cr("Number of virtual space node deaths: " UINTX_FORMAT ".", g_internal_statistics.num_vsnodes_purged);
 372   out->print_cr("Number of times virtual space nodes were expanded: " UINTX_FORMAT ".", g_internal_statistics.num_committed_space_expanded);
 373   out->print_cr("Number of deallocations: " UINTX_FORMAT " (" UINTX_FORMAT " external).", g_internal_statistics.num_deallocs, g_internal_statistics.num_external_deallocs);
 374   out->print_cr("Allocations from deallocated blocks: " UINTX_FORMAT ".", g_internal_statistics.num_allocs_from_deallocated_blocks);
 375   out->print_cr("Number of chunks added to freelist: " UINTX_FORMAT ".",
 376                 g_internal_statistics.num_chunks_added_to_freelist);
 377   out->print_cr("Number of chunks removed from freelist: " UINTX_FORMAT ".",
 378                 g_internal_statistics.num_chunks_removed_from_freelist);
 379   out->print_cr("Number of chunk merges: " UINTX_FORMAT ", split-ups: " UINTX_FORMAT ".",
 380                 g_internal_statistics.num_chunk_merges, g_internal_statistics.num_chunk_splits);
 381 
 382   out->cr();
 383 #endif
 384 
 385   // Print some interesting settings
 386   out->cr();
 387   out->cr();
 388   print_basic_switches(out, scale);
 389 
 390   out->cr();
 391   out->print("InitialBootClassLoaderMetaspaceSize: ");
 392   print_human_readable_size(out, InitialBootClassLoaderMetaspaceSize, scale);
 393 
 394   out->cr();
 395   out->cr();
 396 
 397 } // MetaspaceUtils::print_report()
 398 
 399 } // namespace metaspace
 400