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