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