Path: blob/master/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp
40957 views
/*1* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2018, 2020 SAP SE. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "classfile/classLoaderData.hpp"27#include "classfile/classLoaderDataGraph.hpp"28#include "memory/metaspace.hpp"29#include "memory/metaspace/chunkHeaderPool.hpp"30#include "memory/metaspace/chunkManager.hpp"31#include "memory/metaspace/internalStats.hpp"32#include "memory/metaspace/metaspaceCommon.hpp"33#include "memory/metaspace/metaspaceReporter.hpp"34#include "memory/metaspace/metaspaceSettings.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/metaspaceUtils.hpp"40#include "runtime/os.hpp"4142namespace metaspace {4344static const char* describe_spacetype(Metaspace::MetaspaceType st) {45const char* s = NULL;46switch (st) {47case Metaspace::StandardMetaspaceType: s = "Standard"; break;48case Metaspace::BootMetaspaceType: s = "Boot"; break;49case Metaspace::ClassMirrorHolderMetaspaceType: s = "ClassMirrorHolder"; break;50case Metaspace::ReflectionMetaspaceType: s = "Reflection"; break;51default: ShouldNotReachHere();52}53return s;54}5556static void print_vs(outputStream* out, size_t scale) {57const size_t reserved_nc = RunningCounters::reserved_words_nonclass();58const size_t committed_nc = RunningCounters::committed_words_nonclass();59const int num_nodes_nc = VirtualSpaceList::vslist_nonclass()->num_nodes();6061if (Metaspace::using_class_space()) {62const size_t reserved_c = RunningCounters::reserved_words_class();63const size_t committed_c = RunningCounters::committed_words_class();64const int num_nodes_c = VirtualSpaceList::vslist_class()->num_nodes();6566out->print(" Non-class space: ");67print_scaled_words(out, reserved_nc, scale, 7);68out->print(" reserved, ");69print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7);70out->print(" committed, ");71out->print(" %d nodes.", num_nodes_nc);72out->cr();73out->print(" Class space: ");74print_scaled_words(out, reserved_c, scale, 7);75out->print(" reserved, ");76print_scaled_words_and_percentage(out, committed_c, reserved_c, scale, 7);77out->print(" committed, ");78out->print(" %d nodes.", num_nodes_c);79out->cr();80out->print(" Both: ");81print_scaled_words(out, reserved_c + reserved_nc, scale, 7);82out->print(" reserved, ");83print_scaled_words_and_percentage(out, committed_c + committed_nc, reserved_c + reserved_nc, scale, 7);84out->print(" committed. ");85out->cr();86} else {87print_scaled_words(out, reserved_nc, scale, 7);88out->print(" reserved, ");89print_scaled_words_and_percentage(out, committed_nc, reserved_nc, scale, 7);90out->print(" committed, ");91out->print(" %d nodes.", num_nodes_nc);92out->cr();93}94}9596static void print_settings(outputStream* out, size_t scale) {97out->print("MaxMetaspaceSize: ");98if (MaxMetaspaceSize == max_uintx) {99out->print("unlimited");100} else {101print_human_readable_size(out, MaxMetaspaceSize, scale);102}103out->cr();104if (Metaspace::using_class_space()) {105out->print("CompressedClassSpaceSize: ");106print_human_readable_size(out, CompressedClassSpaceSize, scale);107} else {108out->print("No class space");109}110out->cr();111out->print("Initial GC threshold: ");112print_human_readable_size(out, MetaspaceSize, scale);113out->cr();114out->print("Current GC threshold: ");115print_human_readable_size(out, MetaspaceGC::capacity_until_GC(), scale);116out->cr();117out->print_cr("CDS: %s", (UseSharedSpaces ? "on" : (DumpSharedSpaces ? "dump" : "off")));118out->print_cr("MetaspaceReclaimPolicy: %s", MetaspaceReclaimPolicy);119Settings::print_on(out);120}121122// This will print out a basic metaspace usage report but123// unlike print_report() is guaranteed not to lock or to walk the CLDG.124void MetaspaceReporter::print_basic_report(outputStream* out, size_t scale) {125if (!Metaspace::initialized()) {126out->print_cr("Metaspace not yet initialized.");127return;128}129out->cr();130out->print_cr("Usage:");131if (Metaspace::using_class_space()) {132out->print(" Non-class: ");133}134135// Note: since we want to purely rely on counters, without any locking or walking the CLDG,136// for Usage stats (statistics over in-use chunks) all we can print is the137// used words. We cannot print committed areas, or free/waste areas, of in-use chunks require138// walking.139const size_t used_nc = MetaspaceUtils::used_words(Metaspace::NonClassType);140141print_scaled_words(out, used_nc, scale, 5);142out->print(" used.");143out->cr();144if (Metaspace::using_class_space()) {145const size_t used_c = MetaspaceUtils::used_words(Metaspace::ClassType);146out->print(" Class: ");147print_scaled_words(out, used_c, scale, 5);148out->print(" used.");149out->cr();150out->print(" Both: ");151const size_t used = used_nc + used_c;152print_scaled_words(out, used, scale, 5);153out->print(" used.");154out->cr();155}156out->cr();157out->print_cr("Virtual space:");158print_vs(out, scale);159out->cr();160out->print_cr("Chunk freelists:");161if (Metaspace::using_class_space()) {162out->print(" Non-Class: ");163}164print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size(), scale);165out->cr();166if (Metaspace::using_class_space()) {167out->print(" Class: ");168print_scaled_words(out, ChunkManager::chunkmanager_class()->total_word_size(), scale);169out->cr();170out->print(" Both: ");171print_scaled_words(out, ChunkManager::chunkmanager_nonclass()->total_word_size() +172ChunkManager::chunkmanager_class()->total_word_size(), scale);173out->cr();174}175out->cr();176177// Print basic settings178print_settings(out, scale);179out->cr();180out->cr();181out->print_cr("Internal statistics:");182out->cr();183InternalStats::print_on(out);184out->cr();185}186187void MetaspaceReporter::print_report(outputStream* out, size_t scale, int flags) {188if (!Metaspace::initialized()) {189out->print_cr("Metaspace not yet initialized.");190return;191}192const bool print_loaders = (flags & (int)Option::ShowLoaders) > 0;193const bool print_classes = (flags & (int)Option::ShowClasses) > 0;194const bool print_by_chunktype = (flags & (int)Option::BreakDownByChunkType) > 0;195const bool print_by_spacetype = (flags & (int)Option::BreakDownBySpaceType) > 0;196197// Some report options require walking the class loader data graph.198metaspace::PrintCLDMetaspaceInfoClosure cl(out, scale, print_loaders, print_classes, print_by_chunktype);199if (print_loaders) {200out->cr();201out->print_cr("Usage per loader:");202out->cr();203}204205ClassLoaderDataGraph::loaded_cld_do(&cl); // collect data and optionally print206207// Print totals, broken up by space type.208if (print_by_spacetype) {209out->cr();210out->print_cr("Usage per space type:");211out->cr();212for (int space_type = (int)Metaspace::ZeroMetaspaceType;213space_type < (int)Metaspace::MetaspaceTypeCount; space_type++)214{215uintx num_loaders = cl._num_loaders_by_spacetype[space_type];216uintx num_classes = cl._num_classes_by_spacetype[space_type];217out->print("%s - " UINTX_FORMAT " %s",218describe_spacetype((Metaspace::MetaspaceType)space_type),219num_loaders, loaders_plural(num_loaders));220if (num_classes > 0) {221out->print(", ");222223print_number_of_classes(out, num_classes, cl._num_classes_shared_by_spacetype[space_type]);224out->print(":");225cl._stats_by_spacetype[space_type].print_on(out, scale, print_by_chunktype);226} else {227out->print(".");228out->cr();229}230out->cr();231}232}233234// Print totals for in-use data:235out->cr();236{237uintx num_loaders = cl._num_loaders;238out->print("Total Usage - " UINTX_FORMAT " %s, ",239num_loaders, loaders_plural(num_loaders));240print_number_of_classes(out, cl._num_classes, cl._num_classes_shared);241out->print(":");242cl._stats_total.print_on(out, scale, print_by_chunktype);243out->cr();244}245246/////////////////////////////////////////////////247// -- Print Virtual space.248out->cr();249out->print_cr("Virtual space:");250251print_vs(out, scale);252253// -- Print VirtualSpaceList details.254if ((flags & (int)Option::ShowVSList) > 0) {255out->cr();256out->print_cr("Virtual space list%s:", Metaspace::using_class_space() ? "s" : "");257258if (Metaspace::using_class_space()) {259out->print_cr(" Non-Class:");260}261VirtualSpaceList::vslist_nonclass()->print_on(out);262out->cr();263if (Metaspace::using_class_space()) {264out->print_cr(" Class:");265VirtualSpaceList::vslist_class()->print_on(out);266out->cr();267}268}269out->cr();270271//////////// Freelists (ChunkManager) section ///////////////////////////272273out->cr();274out->print_cr("Chunk freelist%s:", Metaspace::using_class_space() ? "s" : "");275276ChunkManagerStats non_class_cm_stat;277ChunkManagerStats class_cm_stat;278ChunkManagerStats total_cm_stat;279280ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat);281if (Metaspace::using_class_space()) {282ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat);283ChunkManager::chunkmanager_class()->add_to_statistics(&class_cm_stat);284total_cm_stat.add(non_class_cm_stat);285total_cm_stat.add(class_cm_stat);286287out->print_cr(" Non-Class:");288non_class_cm_stat.print_on(out, scale);289out->cr();290out->print_cr(" Class:");291class_cm_stat.print_on(out, scale);292out->cr();293out->print_cr(" Both:");294total_cm_stat.print_on(out, scale);295out->cr();296} else {297ChunkManager::chunkmanager_nonclass()->add_to_statistics(&non_class_cm_stat);298non_class_cm_stat.print_on(out, scale);299out->cr();300}301302//////////// Waste section ///////////////////////////303// As a convenience, print a summary of common waste.304out->cr();305out->print("Waste (unused committed space):");306// For all wastages, print percentages from total. As total use the total size of memory committed for metaspace.307const size_t committed_words = RunningCounters::committed_words();308309out->print("(percentages refer to total committed size ");310print_scaled_words(out, committed_words, scale);311out->print_cr("):");312313// Print waste for in-use chunks.314InUseChunkStats ucs_nonclass = cl._stats_total._arena_stats_nonclass.totals();315InUseChunkStats ucs_class = cl._stats_total._arena_stats_class.totals();316const size_t waste_in_chunks_in_use = ucs_nonclass._waste_words + ucs_class._waste_words;317const size_t free_in_chunks_in_use = ucs_nonclass._free_words + ucs_class._free_words;318319out->print(" Waste in chunks in use: ");320print_scaled_words_and_percentage(out, waste_in_chunks_in_use, committed_words, scale, 6);321out->cr();322out->print(" Free in chunks in use: ");323print_scaled_words_and_percentage(out, free_in_chunks_in_use, committed_words, scale, 6);324out->cr();325326// Print waste in free chunks.327const size_t committed_in_free_chunks = total_cm_stat.total_committed_word_size();328out->print(" In free chunks: ");329print_scaled_words_and_percentage(out, committed_in_free_chunks, committed_words, scale, 6);330out->cr();331332// Print waste in deallocated blocks.333const uintx free_blocks_num =334cl._stats_total._arena_stats_nonclass._free_blocks_num +335cl._stats_total._arena_stats_class._free_blocks_num;336const size_t free_blocks_cap_words =337cl._stats_total._arena_stats_nonclass._free_blocks_word_size +338cl._stats_total._arena_stats_class._free_blocks_word_size;339out->print("Deallocated from chunks in use: ");340print_scaled_words_and_percentage(out, free_blocks_cap_words, committed_words, scale, 6);341out->print(" (" UINTX_FORMAT " blocks)", free_blocks_num);342out->cr();343344// Print total waste.345const size_t total_waste =346waste_in_chunks_in_use +347free_in_chunks_in_use +348committed_in_free_chunks +349free_blocks_cap_words;350out->print(" -total-: ");351print_scaled_words_and_percentage(out, total_waste, committed_words, scale, 6);352out->cr();353354// Also print chunk header pool size.355out->cr();356out->print("chunk header pool: %u items, ", ChunkHeaderPool::pool()->used());357print_scaled_words(out, ChunkHeaderPool::pool()->memory_footprint_words(), scale);358out->print(".");359out->cr();360361// Print internal statistics362out->cr();363out->print_cr("Internal statistics:");364out->cr();365InternalStats::print_on(out);366out->cr();367368// Print some interesting settings369out->cr();370out->print_cr("Settings:");371print_settings(out, scale);372373out->cr();374out->cr();375376DEBUG_ONLY(MetaspaceUtils::verify();)377} // MetaspaceUtils::print_report()378379} // namespace metaspace380381382383