8198691: CodeHeap State Analytics

Reviewed-by: kvn, thartmann
This commit is contained in:
Lutz Schmidt 2018-03-26 12:59:45 -07:00
parent 9b9d9308ed
commit b7cb1a07e4
14 changed files with 2832 additions and 19 deletions

View file

@ -28,6 +28,7 @@
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "code/codeHeapState.hpp"
#include "code/dependencyContext.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
@ -2424,3 +2425,111 @@ void CompileBroker::print_last_compile() {
}
}
}
// Print general/accumulated JIT information.
void CompileBroker::print_info(outputStream *out) {
if (out == NULL) out = tty;
out->cr();
out->print_cr("======================");
out->print_cr(" General JIT info ");
out->print_cr("======================");
out->cr();
out->print_cr(" JIT is : %7s", should_compile_new_jobs() ? "on" : "off");
out->print_cr(" Compiler threads : %7d", (int)CICompilerCount);
out->cr();
out->print_cr("CodeCache overview");
out->print_cr("--------------------------------------------------------");
out->cr();
out->print_cr(" Reserved size : " SIZE_FORMAT_W(7) " KB", CodeCache::max_capacity() / K);
out->print_cr(" Committed size : " SIZE_FORMAT_W(7) " KB", CodeCache::capacity() / K);
out->print_cr(" Unallocated capacity : " SIZE_FORMAT_W(7) " KB", CodeCache::unallocated_capacity() / K);
out->cr();
out->cr();
out->print_cr("CodeCache cleaning overview");
out->print_cr("--------------------------------------------------------");
out->cr();
NMethodSweeper::print(out);
out->print_cr("--------------------------------------------------------");
out->cr();
}
// Note: tty_lock must not be held upon entry to this function.
// Print functions called from herein do "micro-locking" on tty_lock.
// That's a tradeoff which keeps together important blocks of output.
// At the same time, continuous tty_lock hold time is kept in check,
// preventing concurrently printing threads from stalling a long time.
void CompileBroker::print_heapinfo(outputStream* out, const char* function, const char* granularity) {
TimeStamp ts_total;
TimeStamp ts;
bool allFun = !strcmp(function, "all");
bool aggregate = !strcmp(function, "aggregate") || !strcmp(function, "analyze") || allFun;
bool usedSpace = !strcmp(function, "UsedSpace") || allFun;
bool freeSpace = !strcmp(function, "FreeSpace") || allFun;
bool methodCount = !strcmp(function, "MethodCount") || allFun;
bool methodSpace = !strcmp(function, "MethodSpace") || allFun;
bool methodAge = !strcmp(function, "MethodAge") || allFun;
bool methodNames = !strcmp(function, "MethodNames") || allFun;
bool discard = !strcmp(function, "discard") || allFun;
if (out == NULL) {
out = tty;
}
if (!(aggregate || usedSpace || freeSpace || methodCount || methodSpace || methodAge || methodNames || discard)) {
out->print_cr("\n__ CodeHeapStateAnalytics: Function %s is not supported", function);
out->cr();
return;
}
ts_total.update(); // record starting point
if (aggregate) {
print_info(out);
}
// We hold the CodeHeapStateAnalytics_lock all the time, from here until we leave this function.
// That helps us getting a consistent view on the CodeHeap, at least for the "all" function.
// When we request individual parts of the analysis via the jcmd interface, it is possible
// that in between another thread (another jcmd user or the vm running into CodeCache OOM)
// updated the aggregated data. That's a tolerable tradeoff because we can't hold a lock
// across user interaction.
ts.update(); // record starting point
MutexLockerEx mu1(CodeHeapStateAnalytics_lock, Mutex::_no_safepoint_check_flag);
out->cr();
out->print_cr("__ CodeHeapStateAnalytics lock wait took %10.3f seconds _________", ts.seconds());
out->cr();
if (aggregate) {
// It is sufficient to hold the CodeCache_lock only for the aggregate step.
// All other functions operate on aggregated data - except MethodNames, but that should be safe.
// The separate CodeHeapStateAnalytics_lock protects the printing functions against
// concurrent aggregate steps. Acquire this lock before acquiring the CodeCache_lock.
// CodeHeapStateAnalytics_lock could be held by a concurrent thread for a long time,
// leading to an unnecessarily long hold time of the CodeCache_lock.
ts.update(); // record starting point
MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
out->cr();
out->print_cr("__ CodeCache lock wait took %10.3f seconds _________", ts.seconds());
out->cr();
ts.update(); // record starting point
CodeCache::aggregate(out, granularity);
out->cr();
out->print_cr("__ CodeCache lock hold took %10.3f seconds _________", ts.seconds());
out->cr();
}
if (usedSpace) CodeCache::print_usedSpace(out);
if (freeSpace) CodeCache::print_freeSpace(out);
if (methodCount) CodeCache::print_count(out);
if (methodSpace) CodeCache::print_space(out);
if (methodAge) CodeCache::print_age(out);
if (methodNames) CodeCache::print_names(out);
if (discard) CodeCache::discard(out);
out->cr();
out->print_cr("__ CodeHeapStateAnalytics total duration %10.3f seconds _________", ts_total.seconds());
out->cr();
}