6857194: Add hotspot perf counters to aid class loading performance measurement
Summary: Add new jvmstat counters to measure detailed class loading time
Reviewed-by: acorn, kamg
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Jul 10 11:10:00 2009 -0700
@@ -547,7 +547,6 @@
int length,
Handle class_loader,
Handle protection_domain,
- PerfTraceTime* vmtimer,
symbolHandle class_name,
TRAPS) {
ClassFileStream* cfs = stream();
@@ -575,13 +574,11 @@
guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
"Bad interface name in class file %s", CHECK_(nullHandle));
- vmtimer->suspend(); // do not count recursive loading twice
// Call resolve_super so classcircularity is checked
klassOop k = SystemDictionary::resolve_super_or_fail(class_name,
unresolved_klass, class_loader, protection_domain,
false, CHECK_(nullHandle));
interf = KlassHandle(THREAD, k);
- vmtimer->resume();
if (LinkWellKnownClasses) // my super type is well known to me
cp->klass_at_put(interface_index, interf()); // eagerly resolve
@@ -2558,7 +2555,15 @@
ClassFileStream* cfs = stream();
// Timing
- PerfTraceTime vmtimer(ClassLoader::perf_accumulated_time());
+ assert(THREAD->is_Java_thread(), "must be a JavaThread");
+ JavaThread* jt = (JavaThread*) THREAD;
+
+ PerfClassTraceTime ctimer(ClassLoader::perf_class_parse_time(),
+ ClassLoader::perf_class_parse_selftime(),
+ NULL,
+ jt->get_thread_stat()->perf_recursion_counts_addr(),
+ jt->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::PARSE_CLASS);
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
@@ -2738,7 +2743,7 @@
if (itfs_len == 0) {
local_interfaces = objArrayHandle(THREAD, Universe::the_empty_system_obj_array());
} else {
- local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, &vmtimer, _class_name, CHECK_(nullHandle));
+ local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, _class_name, CHECK_(nullHandle));
}
// Fields (offsets are filled in later)
@@ -2782,6 +2787,7 @@
protection_domain,
true,
CHECK_(nullHandle));
+
KlassHandle kh (THREAD, k);
super_klass = instanceKlassHandle(THREAD, kh());
if (LinkWellKnownClasses) // my super class is well known to me
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Jul 10 11:10:00 2009 -0700
@@ -61,7 +61,6 @@
int length,
Handle class_loader,
Handle protection_domain,
- PerfTraceTime* vmtimer,
symbolHandle class_name,
TRAPS);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri Jul 10 11:10:00 2009 -0700
@@ -48,9 +48,26 @@
PerfCounter* ClassLoader::_perf_accumulated_time = NULL;
PerfCounter* ClassLoader::_perf_classes_inited = NULL;
PerfCounter* ClassLoader::_perf_class_init_time = NULL;
+PerfCounter* ClassLoader::_perf_class_init_selftime = NULL;
+PerfCounter* ClassLoader::_perf_classes_verified = NULL;
PerfCounter* ClassLoader::_perf_class_verify_time = NULL;
+PerfCounter* ClassLoader::_perf_class_verify_selftime = NULL;
PerfCounter* ClassLoader::_perf_classes_linked = NULL;
PerfCounter* ClassLoader::_perf_class_link_time = NULL;
+PerfCounter* ClassLoader::_perf_class_link_selftime = NULL;
+PerfCounter* ClassLoader::_perf_class_parse_time = NULL;
+PerfCounter* ClassLoader::_perf_class_parse_selftime = NULL;
+PerfCounter* ClassLoader::_perf_sys_class_lookup_time = NULL;
+PerfCounter* ClassLoader::_perf_shared_classload_time = NULL;
+PerfCounter* ClassLoader::_perf_sys_classload_time = NULL;
+PerfCounter* ClassLoader::_perf_app_classload_time = NULL;
+PerfCounter* ClassLoader::_perf_app_classload_selftime = NULL;
+PerfCounter* ClassLoader::_perf_app_classload_count = NULL;
+PerfCounter* ClassLoader::_perf_define_appclasses = NULL;
+PerfCounter* ClassLoader::_perf_define_appclass_time = NULL;
+PerfCounter* ClassLoader::_perf_define_appclass_selftime = NULL;
+PerfCounter* ClassLoader::_perf_app_classfile_bytes_read = NULL;
+PerfCounter* ClassLoader::_perf_sys_classfile_bytes_read = NULL;
PerfCounter* ClassLoader::_sync_systemLoaderLockContentionRate = NULL;
PerfCounter* ClassLoader::_sync_nonSystemLoaderLockContentionRate = NULL;
PerfCounter* ClassLoader::_sync_JVMFindLoadedClassLockFreeCounter = NULL;
@@ -152,6 +169,9 @@
hpi::close(file_handle);
// construct ClassFileStream
if (num_read == (size_t)st.st_size) {
+ if (UsePerfData) {
+ ClassLoader::perf_sys_classfile_bytes_read()->inc(num_read);
+ }
return new ClassFileStream(buffer, st.st_size, _dir); // Resource allocated
}
}
@@ -198,6 +218,9 @@
buffer = NEW_RESOURCE_ARRAY(u1, filesize);
if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL;
}
+ if (UsePerfData) {
+ ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
+ }
// return result
return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated
}
@@ -825,7 +848,9 @@
ClassFileStream* stream = NULL;
int classpath_index = 0;
{
- PerfTraceTime vmtimer(perf_accumulated_time());
+ PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
+ ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::CLASS_LOAD);
ClassPathEntry* e = _first_entry;
while (e != NULL) {
stream = e->open_stream(name);
@@ -890,11 +915,29 @@
// jvmstat performance counters
NEWPERFTICKCOUNTER(_perf_accumulated_time, SUN_CLS, "time");
NEWPERFTICKCOUNTER(_perf_class_init_time, SUN_CLS, "classInitTime");
+ NEWPERFTICKCOUNTER(_perf_class_init_selftime, SUN_CLS, "classInitTime.self");
NEWPERFTICKCOUNTER(_perf_class_verify_time, SUN_CLS, "classVerifyTime");
+ NEWPERFTICKCOUNTER(_perf_class_verify_selftime, SUN_CLS, "classVerifyTime.self");
NEWPERFTICKCOUNTER(_perf_class_link_time, SUN_CLS, "classLinkedTime");
-
+ NEWPERFTICKCOUNTER(_perf_class_link_selftime, SUN_CLS, "classLinkedTime.self");
NEWPERFEVENTCOUNTER(_perf_classes_inited, SUN_CLS, "initializedClasses");
NEWPERFEVENTCOUNTER(_perf_classes_linked, SUN_CLS, "linkedClasses");
+ NEWPERFEVENTCOUNTER(_perf_classes_verified, SUN_CLS, "verifiedClasses");
+
+ NEWPERFTICKCOUNTER(_perf_class_parse_time, SUN_CLS, "parseClassTime");
+ NEWPERFTICKCOUNTER(_perf_class_parse_selftime, SUN_CLS, "parseClassTime.self");
+ NEWPERFTICKCOUNTER(_perf_sys_class_lookup_time, SUN_CLS, "lookupSysClassTime");
+ NEWPERFTICKCOUNTER(_perf_shared_classload_time, SUN_CLS, "sharedClassLoadTime");
+ NEWPERFTICKCOUNTER(_perf_sys_classload_time, SUN_CLS, "sysClassLoadTime");
+ NEWPERFTICKCOUNTER(_perf_app_classload_time, SUN_CLS, "appClassLoadTime");
+ NEWPERFTICKCOUNTER(_perf_app_classload_selftime, SUN_CLS, "appClassLoadTime.self");
+ NEWPERFEVENTCOUNTER(_perf_app_classload_count, SUN_CLS, "appClassLoadCount");
+ NEWPERFTICKCOUNTER(_perf_define_appclasses, SUN_CLS, "defineAppClasses");
+ NEWPERFTICKCOUNTER(_perf_define_appclass_time, SUN_CLS, "defineAppClassTime");
+ NEWPERFTICKCOUNTER(_perf_define_appclass_selftime, SUN_CLS, "defineAppClassTime.self");
+ NEWPERFBYTECOUNTER(_perf_app_classfile_bytes_read, SUN_CLS, "appClassBytes");
+ NEWPERFBYTECOUNTER(_perf_sys_classfile_bytes_read, SUN_CLS, "sysClassBytes");
+
// The following performance counters are added for measuring the impact
// of the bug fix of 6365597. They are mainly focused on finding out
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp Fri Jul 10 11:10:00 2009 -0700
@@ -149,9 +149,26 @@
static PerfCounter* _perf_accumulated_time;
static PerfCounter* _perf_classes_inited;
static PerfCounter* _perf_class_init_time;
+ static PerfCounter* _perf_class_init_selftime;
+ static PerfCounter* _perf_classes_verified;
static PerfCounter* _perf_class_verify_time;
+ static PerfCounter* _perf_class_verify_selftime;
static PerfCounter* _perf_classes_linked;
static PerfCounter* _perf_class_link_time;
+ static PerfCounter* _perf_class_link_selftime;
+ static PerfCounter* _perf_class_parse_time;
+ static PerfCounter* _perf_class_parse_selftime;
+ static PerfCounter* _perf_sys_class_lookup_time;
+ static PerfCounter* _perf_shared_classload_time;
+ static PerfCounter* _perf_sys_classload_time;
+ static PerfCounter* _perf_app_classload_time;
+ static PerfCounter* _perf_app_classload_selftime;
+ static PerfCounter* _perf_app_classload_count;
+ static PerfCounter* _perf_define_appclasses;
+ static PerfCounter* _perf_define_appclass_time;
+ static PerfCounter* _perf_define_appclass_selftime;
+ static PerfCounter* _perf_app_classfile_bytes_read;
+ static PerfCounter* _perf_sys_classfile_bytes_read;
static PerfCounter* _sync_systemLoaderLockContentionRate;
static PerfCounter* _sync_nonSystemLoaderLockContentionRate;
@@ -196,12 +213,29 @@
static void print_bootclasspath();
// Timing
- static PerfCounter* perf_accumulated_time() { return _perf_accumulated_time; }
- static PerfCounter* perf_classes_inited() { return _perf_classes_inited; }
- static PerfCounter* perf_class_init_time() { return _perf_class_init_time; }
- static PerfCounter* perf_class_verify_time() { return _perf_class_verify_time; }
- static PerfCounter* perf_classes_linked() { return _perf_classes_linked; }
- static PerfCounter* perf_class_link_time() { return _perf_class_link_time; }
+ static PerfCounter* perf_accumulated_time() { return _perf_accumulated_time; }
+ static PerfCounter* perf_classes_inited() { return _perf_classes_inited; }
+ static PerfCounter* perf_class_init_time() { return _perf_class_init_time; }
+ static PerfCounter* perf_class_init_selftime() { return _perf_class_init_selftime; }
+ static PerfCounter* perf_classes_verified() { return _perf_classes_verified; }
+ static PerfCounter* perf_class_verify_time() { return _perf_class_verify_time; }
+ static PerfCounter* perf_class_verify_selftime() { return _perf_class_verify_selftime; }
+ static PerfCounter* perf_classes_linked() { return _perf_classes_linked; }
+ static PerfCounter* perf_class_link_time() { return _perf_class_link_time; }
+ static PerfCounter* perf_class_link_selftime() { return _perf_class_link_selftime; }
+ static PerfCounter* perf_class_parse_time() { return _perf_class_parse_time; }
+ static PerfCounter* perf_class_parse_selftime() { return _perf_class_parse_selftime; }
+ static PerfCounter* perf_sys_class_lookup_time() { return _perf_sys_class_lookup_time; }
+ static PerfCounter* perf_shared_classload_time() { return _perf_shared_classload_time; }
+ static PerfCounter* perf_sys_classload_time() { return _perf_sys_classload_time; }
+ static PerfCounter* perf_app_classload_time() { return _perf_app_classload_time; }
+ static PerfCounter* perf_app_classload_selftime() { return _perf_app_classload_selftime; }
+ static PerfCounter* perf_app_classload_count() { return _perf_app_classload_count; }
+ static PerfCounter* perf_define_appclasses() { return _perf_define_appclasses; }
+ static PerfCounter* perf_define_appclass_time() { return _perf_define_appclass_time; }
+ static PerfCounter* perf_define_appclass_selftime() { return _perf_define_appclass_selftime; }
+ static PerfCounter* perf_app_classfile_bytes_read() { return _perf_app_classfile_bytes_read; }
+ static PerfCounter* perf_sys_classfile_bytes_read() { return _perf_sys_classfile_bytes_read; }
// Record how often system loader lock object is contended
static PerfCounter* sync_systemLoaderLockContentionRate() {
@@ -307,3 +341,118 @@
static int compile_the_world_counter() { return _compile_the_world_counter; }
#endif //PRODUCT
};
+
+// PerfClassTraceTime is used to measure time for class loading related events.
+// This class tracks cumulative time and exclusive time for specific event types.
+// During the execution of one event, other event types (e.g. class loading and
+// resolution) as well as recursive calls of the same event type could happen.
+// Only one elapsed timer (cumulative) and one thread-local self timer (exclusive)
+// (i.e. only one event type) are active at a time even multiple PerfClassTraceTime
+// instances have been created as multiple events are happening.
+class PerfClassTraceTime {
+ public:
+ enum {
+ CLASS_LOAD = 0,
+ PARSE_CLASS = 1,
+ CLASS_LINK = 2,
+ CLASS_VERIFY = 3,
+ CLASS_CLINIT = 4,
+ DEFINE_CLASS = 5,
+ EVENT_TYPE_COUNT = 6
+ };
+ protected:
+ // _t tracks time from initialization to destruction of this timer instance
+ // including time for all other event types, and recursive calls of this type.
+ // When a timer is called recursively, the elapsedTimer _t would not be used.
+ elapsedTimer _t;
+ PerfLongCounter* _timep;
+ PerfLongCounter* _selftimep;
+ PerfLongCounter* _eventp;
+ // pointer to thread-local recursion counter and timer array
+ // The thread_local timers track cumulative time for specific event types
+ // exclusive of time for other event types, but including recursive calls
+ // of the same type.
+ int* _recursion_counters;
+ elapsedTimer* _timers;
+ int _event_type;
+ int _prev_active_event;
+
+ public:
+
+ inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */
+ PerfLongCounter* selftimep, /* counter incremented with exclusive time */
+ PerfLongCounter* eventp, /* event counter */
+ int* recursion_counters, /* thread-local recursion counter array */
+ elapsedTimer* timers, /* thread-local timer array */
+ int type /* event type */ ) :
+ _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) {
+ initialize();
+ }
+
+ inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */
+ elapsedTimer* timers, /* thread-local timer array */
+ int type /* event type */ ) :
+ _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) {
+ initialize();
+ }
+
+ void initialize() {
+ if (!UsePerfData) return;
+
+ if (_eventp != NULL) {
+ // increment the event counter
+ _eventp->inc();
+ }
+
+ // stop the current active thread-local timer to measure inclusive time
+ _prev_active_event = -1;
+ for (int i=0; i < EVENT_TYPE_COUNT; i++) {
+ if (_timers[i].is_active()) {
+ assert(_prev_active_event == -1, "should have only one active timer");
+ _prev_active_event = i;
+ _timers[i].stop();
+ }
+ }
+
+ if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) {
+ // start the inclusive timer if not recursively called
+ _t.start();
+ }
+
+ // start thread-local timer of the given event type
+ if (!_timers[_event_type].is_active()) {
+ _timers[_event_type].start();
+ }
+ }
+
+ inline void suspend() { _t.stop(); _timers[_event_type].stop(); }
+ inline void resume() { _t.start(); _timers[_event_type].start(); }
+
+ ~PerfClassTraceTime() {
+ if (!UsePerfData) return;
+
+ // stop the thread-local timer as the event completes
+ // and resume the thread-local timer of the event next on the stack
+ _timers[_event_type].stop();
+ jlong selftime = _timers[_event_type].ticks();
+
+ if (_prev_active_event >= 0) {
+ _timers[_prev_active_event].start();
+ }
+
+ if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return;
+
+ // increment the counters only on the leaf call
+ _t.stop();
+ _timep->inc(_t.ticks());
+ if (_selftimep != NULL) {
+ _selftimep->inc(selftime);
+ }
+ // add all class loading related event selftime to the accumulated time counter
+ ClassLoader::perf_accumulated_time()->inc(selftime);
+
+ // reset the timer
+ _timers[_event_type].reset();
+ }
+};
+
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Jul 10 11:10:00 2009 -0700
@@ -1306,13 +1306,18 @@
instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_name, Handle class_loader, TRAPS) {
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
if (class_loader.is_null()) {
+
// Search the shared system dictionary for classes preloaded into the
// shared spaces.
instanceKlassHandle k;
- k = load_shared_class(class_name, class_loader, THREAD);
+ {
+ PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());
+ k = load_shared_class(class_name, class_loader, THREAD);
+ }
if (k.is_null()) {
// Use VM class loader
+ PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
k = ClassLoader::load_classfile(class_name, CHECK_(nh));
}
@@ -1334,6 +1339,16 @@
// Use user specified class loader to load class. Call loadClass operation on class_loader.
ResourceMark rm(THREAD);
+ assert(THREAD->is_Java_thread(), "must be a JavaThread");
+ JavaThread* jt = (JavaThread*) THREAD;
+
+ PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time(),
+ ClassLoader::perf_app_classload_selftime(),
+ ClassLoader::perf_app_classload_count(),
+ jt->get_thread_stat()->perf_recursion_counts_addr(),
+ jt->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::CLASS_LOAD);
+
Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nh));
// Translate to external class name format, i.e., convert '/' chars to '.'
Handle string = java_lang_String::externalize_classname(s, CHECK_(nh));
--- a/hotspot/src/share/vm/includeDB_core Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_core Fri Jul 10 11:10:00 2009 -0700
@@ -874,6 +874,7 @@
classFileParser.cpp symbolOop.hpp
classFileParser.cpp symbolTable.hpp
classFileParser.cpp systemDictionary.hpp
+classFileParser.cpp threadService.hpp
classFileParser.cpp timer.hpp
classFileParser.cpp universe.inline.hpp
classFileParser.cpp verificationType.hpp
@@ -926,6 +927,7 @@
classLoader.cpp symbolOop.hpp
classLoader.cpp systemDictionary.hpp
classLoader.cpp threadCritical.hpp
+classLoader.cpp threadService.hpp
classLoader.cpp timer.hpp
classLoader.cpp universe.inline.hpp
classLoader.cpp vmSymbols.hpp
@@ -4026,6 +4028,7 @@
systemDictionary.cpp resolutionErrors.hpp
systemDictionary.cpp signature.hpp
systemDictionary.cpp systemDictionary.hpp
+systemDictionary.cpp threadService.hpp
systemDictionary.cpp typeArrayKlass.hpp
systemDictionary.cpp vmSymbols.hpp
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Jul 10 11:10:00 2009 -0700
@@ -158,9 +158,6 @@
// timer handles recursion
assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl");
JavaThread* jt = (JavaThread*)THREAD;
- PerfTraceTimedEvent vmtimer(ClassLoader::perf_class_link_time(),
- ClassLoader::perf_classes_linked(),
- jt->get_thread_stat()->class_link_recursion_count_addr());
// link super class before linking this class
instanceKlassHandle super(THREAD, this_oop->super());
@@ -194,6 +191,15 @@
return true;
}
+ // trace only the link time for this klass that includes
+ // the verification time
+ PerfClassTraceTime vmtimer(ClassLoader::perf_class_link_time(),
+ ClassLoader::perf_class_link_selftime(),
+ ClassLoader::perf_classes_linked(),
+ jt->get_thread_stat()->perf_recursion_counts_addr(),
+ jt->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::CLASS_LINK);
+
// verification & rewriting
{
ObjectLocker ol(this_oop, THREAD);
@@ -203,12 +209,14 @@
if (!this_oop->is_linked()) {
if (!this_oop->is_rewritten()) {
{
- assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl");
- JavaThread* jt = (JavaThread*)THREAD;
// Timer includes any side effects of class verification (resolution,
// etc), but not recursive entry into verify_code().
- PerfTraceTime timer(ClassLoader::perf_class_verify_time(),
- jt->get_thread_stat()->class_verify_recursion_count_addr());
+ PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
+ ClassLoader::perf_class_verify_selftime(),
+ ClassLoader::perf_classes_verified(),
+ jt->get_thread_stat()->perf_recursion_counts_addr(),
+ jt->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::CLASS_VERIFY);
bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD);
if (!verify_ok) {
return false;
@@ -350,9 +358,12 @@
JavaThread* jt = (JavaThread*)THREAD;
// Timer includes any side effects of class initialization (resolution,
// etc), but not recursive entry into call_class_initializer().
- PerfTraceTimedEvent timer(ClassLoader::perf_class_init_time(),
- ClassLoader::perf_classes_inited(),
- jt->get_thread_stat()->class_init_recursion_count_addr());
+ PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),
+ ClassLoader::perf_class_init_selftime(),
+ ClassLoader::perf_classes_inited(),
+ jt->get_thread_stat()->perf_recursion_counts_addr(),
+ jt->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::CLASS_CLINIT);
this_oop->call_class_initializer(THREAD);
}
--- a/hotspot/src/share/vm/prims/jvm.cpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp Fri Jul 10 11:10:00 2009 -0700
@@ -756,6 +756,20 @@
static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) {
if (source == NULL) source = "__JVM_DefineClass__";
+ assert(THREAD->is_Java_thread(), "must be a JavaThread");
+ JavaThread* jt = (JavaThread*) THREAD;
+
+ PerfClassTraceTime vmtimer(ClassLoader::perf_define_appclass_time(),
+ ClassLoader::perf_define_appclass_selftime(),
+ ClassLoader::perf_define_appclasses(),
+ jt->get_thread_stat()->perf_recursion_counts_addr(),
+ jt->get_thread_stat()->perf_timers_addr(),
+ PerfClassTraceTime::DEFINE_CLASS);
+
+ if (UsePerfData) {
+ ClassLoader::perf_app_classfile_bytes_read()->inc(len);
+ }
+
// Since exceptions can be thrown, class initialization can take place
// if name is NULL no check for class name in .class stream has to be made.
symbolHandle class_name;
--- a/hotspot/src/share/vm/runtime/perfData.hpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/runtime/perfData.hpp Fri Jul 10 11:10:00 2009 -0700
@@ -868,6 +868,10 @@
{counter = PerfDataManager::create_counter(counter_ns, counter_name, \
PerfData::U_Events,CHECK);}
+#define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
+ {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
+ PerfData::U_Bytes,CHECK);}
+
// Utility Classes
/*
--- a/hotspot/src/share/vm/services/threadService.cpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/services/threadService.cpp Fri Jul 10 11:10:00 2009 -0700
@@ -688,10 +688,9 @@
_contended_enter_count = 0;
_monitor_wait_count = 0;
_sleep_count = 0;
- _class_init_recursion_count = 0;
- _class_verify_recursion_count = 0;
_count_pending_reset = false;
_timer_pending_reset = false;
+ memset((void*) _perf_recursion_counts, 0, sizeof(_perf_recursion_counts));
}
ThreadSnapshot::ThreadSnapshot(JavaThread* thread) {
--- a/hotspot/src/share/vm/services/threadService.hpp Fri Jun 19 07:33:25 2009 -0700
+++ b/hotspot/src/share/vm/services/threadService.hpp Fri Jul 10 11:10:00 2009 -0700
@@ -120,9 +120,8 @@
bool _timer_pending_reset;
// Keep accurate times for potentially recursive class operations
- int _class_init_recursion_count;
- int _class_verify_recursion_count;
- int _class_link_recursion_count;
+ int _perf_recursion_counts[6];
+ elapsedTimer _perf_timers[6];
// utility functions
void check_and_reset_count() {
@@ -165,9 +164,8 @@
void reset_count_stat() { _count_pending_reset = true; }
void reset_time_stat() { _timer_pending_reset = true; }
- int* class_init_recursion_count_addr() { return &_class_init_recursion_count; }
- int* class_verify_recursion_count_addr() { return &_class_verify_recursion_count; }
- int* class_link_recursion_count_addr() { return &_class_link_recursion_count; }
+ int* perf_recursion_counts_addr() { return _perf_recursion_counts; }
+ elapsedTimer* perf_timers_addr() { return _perf_timers; }
};
// Thread snapshot to represent the thread state and statistics