8277383: VM.metaspace optionally show chunk freelist details

Reviewed-by: coleenp, shade
This commit is contained in:
Thomas Stuefe 2021-12-07 14:15:04 +00:00
parent 44fcee3830
commit 35361270cb
5 changed files with 48 additions and 1 deletions

View File

@ -42,6 +42,7 @@ MetaspaceDCmd::MetaspaceDCmd(outputStream* output, bool heap) :
_by_spacetype("by-spacetype", "Break down numbers by loader type.", "BOOLEAN", false, "false"),
_by_chunktype("by-chunktype", "Break down numbers by chunk type.", "BOOLEAN", false, "false"),
_show_vslist("vslist", "Shows details about the underlying virtual space.", "BOOLEAN", false, "false"),
_show_chunkfreelist("chunkfreelist", "Shows details about global chunk free lists (ChunkManager).", "BOOLEAN", false, "false"),
_scale("scale", "Memory usage in which to scale. Valid values are: 1, KB, MB or GB (fixed scale) "
"or \"dynamic\" for a dynamically chosen scale.",
"STRING", false, "dynamic"),
@ -53,6 +54,7 @@ MetaspaceDCmd::MetaspaceDCmd(outputStream* output, bool heap) :
_dcmdparser.add_dcmd_option(&_by_chunktype);
_dcmdparser.add_dcmd_option(&_by_spacetype);
_dcmdparser.add_dcmd_option(&_show_vslist);
_dcmdparser.add_dcmd_option(&_show_chunkfreelist);
_dcmdparser.add_dcmd_option(&_scale);
}
@ -96,6 +98,7 @@ void MetaspaceDCmd::execute(DCmdSource source, TRAPS) {
if (_by_chunktype.value()) flags |= (int)MetaspaceReporter::Option::BreakDownByChunkType;
if (_by_spacetype.value()) flags |= (int)MetaspaceReporter::Option::BreakDownBySpaceType;
if (_show_vslist.value()) flags |= (int)MetaspaceReporter::Option::ShowVSList;
if (_show_chunkfreelist.value()) flags |= (int)MetaspaceReporter::Option::ShowChunkFreeList;
VM_PrintMetadata op(output(), scale, flags);
VMThread::execute(&op);
}

View File

@ -38,6 +38,7 @@ class MetaspaceDCmd : public DCmdWithParser {
DCmdArgument<bool> _by_spacetype;
DCmdArgument<bool> _by_chunktype;
DCmdArgument<bool> _show_vslist;
DCmdArgument<bool> _show_chunkfreelist;
DCmdArgument<char*> _scale;
DCmdArgument<bool> _show_classes;
public:

View File

@ -300,6 +300,24 @@ void MetaspaceReporter::print_report(outputStream* out, size_t scale, int flags)
out->cr();
}
// -- Print Chunkmanager details.
if ((flags & (int)Option::ShowChunkFreeList) > 0) {
out->cr();
out->print_cr("Chunk freelist details:");
if (Metaspace::using_class_space()) {
out->print_cr(" Non-Class:");
}
ChunkManager::chunkmanager_nonclass()->print_on(out);
out->cr();
if (Metaspace::using_class_space()) {
out->print_cr(" Class:");
ChunkManager::chunkmanager_class()->print_on(out);
out->cr();
}
}
out->cr();
//////////// Waste section ///////////////////////////
// As a convenience, print a summary of common waste.
out->cr();

View File

@ -44,7 +44,9 @@ public:
// Print details about the underlying virtual spaces.
ShowVSList = (1 << 3),
// If show_loaders: show loaded classes for each loader.
ShowClasses = (1 << 4)
ShowClasses = (1 << 4),
// Print details about the underlying virtual spaces.
ShowChunkFreeList = (1 << 5)
};
// This will print out a basic metaspace usage report but

View File

@ -168,6 +168,29 @@ public class PrintMetaspaceDcmd {
output.shouldContain("Virtual space list");
output.shouldMatch("node.*reserved.*committed.*used.*");
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "chunkfreelist"});
// Output should look somewhat like this...
// vvvvvvvvvvvvvvvv
// Chunk freelist details:
// Non-Class:
// cm non-class-space: 5 chunks, total word size: 402944.
// -- List[lv00]: empty
// -- List[lv01]: - <Chunk @0x00007f925c124090, state f, base 0x00007f9208600000, level lv01 (262144 words), used 0 words, committed 0 words.> - total : 1 chunks.
// -- List[lv02]: - <Chunk @0x00007f925c1240d8, state f, base 0x00007f9208500000, level lv02 (131072 words), used 0 words, committed 0 words.> - total : 1 chunks.
// -- List[lv03]: empty
// .....
//
// total chunks: 5, total word size: 402944.
// ^^^^^^^^^^^^^^^^^
// .... but the actual number of chunks in the freelist is difficult to predict and may be low or zero since
// no class unloading happened yet.
output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
output.shouldContain("Chunk freelist details:");
// ... but we should see at least one one chunk somewhere, the list should never be empty.
output.shouldMatch(".*-- List\\[lv00\\].*");
output.shouldMatch(".*total chunks.*total word size.*");
// Test with different scales
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "scale=G"});
output = new OutputAnalyzer(pb.start());