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