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