8005885: enhance PrintCodeCache to print more data
Reviewed-by: xliu, phh
This commit is contained in:
parent
23995f822e
commit
b6843a1624
@ -101,22 +101,37 @@ class CodeBlob_sizes {
|
||||
scopes_pcs_size = 0;
|
||||
}
|
||||
|
||||
int total() { return total_size; }
|
||||
bool is_empty() { return count == 0; }
|
||||
int total() const { return total_size; }
|
||||
bool is_empty() const { return count == 0; }
|
||||
|
||||
void print(const char* title) {
|
||||
tty->print_cr(" #%d %s = %dK (hdr %d%%, loc %d%%, code %d%%, stub %d%%, [oops %d%%, metadata %d%%, data %d%%, pcs %d%%])",
|
||||
count,
|
||||
title,
|
||||
(int)(total() / K),
|
||||
header_size * 100 / total_size,
|
||||
relocation_size * 100 / total_size,
|
||||
code_size * 100 / total_size,
|
||||
stub_size * 100 / total_size,
|
||||
scopes_oop_size * 100 / total_size,
|
||||
scopes_metadata_size * 100 / total_size,
|
||||
scopes_data_size * 100 / total_size,
|
||||
scopes_pcs_size * 100 / total_size);
|
||||
void print(const char* title) const {
|
||||
if (is_empty()) {
|
||||
tty->print_cr(" #%d %s = %dK",
|
||||
count,
|
||||
title,
|
||||
total() / (int)K);
|
||||
} else {
|
||||
tty->print_cr(" #%d %s = %dK (hdr %dK %d%%, loc %dK %d%%, code %dK %d%%, stub %dK %d%%, [oops %dK %d%%, metadata %dK %d%%, data %dK %d%%, pcs %dK %d%%])",
|
||||
count,
|
||||
title,
|
||||
total() / (int)K,
|
||||
header_size / (int)K,
|
||||
header_size * 100 / total_size,
|
||||
relocation_size / (int)K,
|
||||
relocation_size * 100 / total_size,
|
||||
code_size / (int)K,
|
||||
code_size * 100 / total_size,
|
||||
stub_size / (int)K,
|
||||
stub_size * 100 / total_size,
|
||||
scopes_oop_size / (int)K,
|
||||
scopes_oop_size * 100 / total_size,
|
||||
scopes_metadata_size / (int)K,
|
||||
scopes_metadata_size * 100 / total_size,
|
||||
scopes_data_size / (int)K,
|
||||
scopes_data_size * 100 / total_size,
|
||||
scopes_pcs_size / (int)K,
|
||||
scopes_pcs_size * 100 / total_size);
|
||||
}
|
||||
}
|
||||
|
||||
void add(CodeBlob* cb) {
|
||||
@ -1427,27 +1442,73 @@ void CodeCache::print() {
|
||||
#ifndef PRODUCT
|
||||
if (!Verbose) return;
|
||||
|
||||
CodeBlob_sizes live;
|
||||
CodeBlob_sizes dead;
|
||||
CodeBlob_sizes live[CompLevel_full_optimization + 1];
|
||||
CodeBlob_sizes dead[CompLevel_full_optimization + 1];
|
||||
CodeBlob_sizes runtimeStub;
|
||||
CodeBlob_sizes uncommonTrapStub;
|
||||
CodeBlob_sizes deoptimizationStub;
|
||||
CodeBlob_sizes adapter;
|
||||
CodeBlob_sizes bufferBlob;
|
||||
CodeBlob_sizes other;
|
||||
|
||||
FOR_ALL_ALLOCABLE_HEAPS(heap) {
|
||||
FOR_ALL_BLOBS(cb, *heap) {
|
||||
if (!cb->is_alive()) {
|
||||
dead.add(cb);
|
||||
if (cb->is_nmethod()) {
|
||||
const int level = cb->as_nmethod()->comp_level();
|
||||
assert(0 <= level && level <= CompLevel_full_optimization, "Invalid compilation level");
|
||||
if (!cb->is_alive()) {
|
||||
dead[level].add(cb);
|
||||
} else {
|
||||
live[level].add(cb);
|
||||
}
|
||||
} else if (cb->is_runtime_stub()) {
|
||||
runtimeStub.add(cb);
|
||||
} else if (cb->is_deoptimization_stub()) {
|
||||
deoptimizationStub.add(cb);
|
||||
} else if (cb->is_uncommon_trap_stub()) {
|
||||
uncommonTrapStub.add(cb);
|
||||
} else if (cb->is_adapter_blob()) {
|
||||
adapter.add(cb);
|
||||
} else if (cb->is_buffer_blob()) {
|
||||
bufferBlob.add(cb);
|
||||
} else {
|
||||
live.add(cb);
|
||||
other.add(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tty->print_cr("CodeCache:");
|
||||
tty->print_cr("nmethod dependency checking time %fs", dependentCheckTime.seconds());
|
||||
|
||||
if (!live.is_empty()) {
|
||||
live.print("live");
|
||||
tty->print_cr("nmethod blobs per compilation level:");
|
||||
for (int i = 0; i <= CompLevel_full_optimization; i++) {
|
||||
const char *level_name;
|
||||
switch (i) {
|
||||
case CompLevel_none: level_name = "none"; break;
|
||||
case CompLevel_simple: level_name = "simple"; break;
|
||||
case CompLevel_limited_profile: level_name = "limited profile"; break;
|
||||
case CompLevel_full_profile: level_name = "full profile"; break;
|
||||
case CompLevel_full_optimization: level_name = "full optimization"; break;
|
||||
default: assert(false, "invalid compilation level");
|
||||
}
|
||||
tty->print_cr("%s:", level_name);
|
||||
live[i].print("live");
|
||||
dead[i].print("dead");
|
||||
}
|
||||
if (!dead.is_empty()) {
|
||||
dead.print("dead");
|
||||
|
||||
struct {
|
||||
const char* name;
|
||||
const CodeBlob_sizes* sizes;
|
||||
} non_nmethod_blobs[] = {
|
||||
{ "runtime", &runtimeStub },
|
||||
{ "uncommon trap", &uncommonTrapStub },
|
||||
{ "deoptimization", &deoptimizationStub },
|
||||
{ "adapter", &adapter },
|
||||
{ "buffer blob", &bufferBlob },
|
||||
{ "other", &other },
|
||||
};
|
||||
tty->print_cr("Non-nmethod blobs:");
|
||||
for (auto& blob: non_nmethod_blobs) {
|
||||
blob.sizes->print(blob.name);
|
||||
}
|
||||
|
||||
if (WizardMode) {
|
||||
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test CheckCodeCacheInfo
|
||||
* @bug 8005885
|
||||
* @summary Checks VM verbose information related to the code cache
|
||||
* @library /test/lib
|
||||
* @requires vm.debug
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller
|
||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||
* compiler.codecache.CheckCodeCacheInfo
|
||||
*/
|
||||
|
||||
package compiler.codecache;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class CheckCodeCacheInfo {
|
||||
private static final String VERBOSE_REGEXP;
|
||||
|
||||
static {
|
||||
String entry = "\\d+K( \\(hdr \\d+K \\d+%, loc \\d+K \\d+%, code \\d+K \\d+%, stub \\d+K \\d+%, \\[oops \\d+K \\d+%, metadata \\d+K \\d+%, data \\d+K \\d+%, pcs \\d+K \\d+%\\]\\))?\\n";
|
||||
String pair = " #\\d+ live = " + entry
|
||||
+ " #\\d+ dead = " + entry;
|
||||
|
||||
VERBOSE_REGEXP = "nmethod blobs per compilation level:\\n"
|
||||
+ "none:\\n"
|
||||
+ pair
|
||||
+ "simple:\\n"
|
||||
+ pair
|
||||
+ "limited profile:\\n"
|
||||
+ pair
|
||||
+ "full profile:\\n"
|
||||
+ pair
|
||||
+ "full optimization:\\n"
|
||||
+ pair
|
||||
+ "Non-nmethod blobs:\\n"
|
||||
+ " #\\d+ runtime = " + entry
|
||||
+ " #\\d+ uncommon trap = " + entry
|
||||
+ " #\\d+ deoptimization = " + entry
|
||||
+ " #\\d+ adapter = " + entry
|
||||
+ " #\\d+ buffer blob = " + entry
|
||||
+ " #\\d+ other = " + entry;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProcessBuilder pb;
|
||||
|
||||
pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintCodeCache",
|
||||
"-XX:+Verbose",
|
||||
"-version");
|
||||
OutputAnalyzer out = new OutputAnalyzer(pb.start());
|
||||
out.shouldHaveExitValue(0);
|
||||
out.stdoutShouldMatch(VERBOSE_REGEXP);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user