From: Petr L. <lu...@us...> - 2001-08-24 17:54:08
|
Update of /cvsroot/javaprofiler/library/src/prof In directory usw-pr-cvs1:/tmp/cvs-serv4667/prof Modified Files: Makefile.rules dir.info prof.cpp prof.h prof_get.cpp prof_jvm.cpp Added Files: prof_monitor.cpp Log Message: Monitor profiling --- NEW FILE: prof_monitor.cpp --- #include "../main/includes.h" void Prof::event_monitorContendedEnter( JVMPI_Event* event) { Synchronized sync(dataLock); // cerr << "MONITOR CONTENDED ENTER: " << (long)(event->env_id) << endl; Thread* t; if (!(t = getThread(event->env_id))) { PROF_ERROR("MONITOR CONTENDED ENTER", "Thread not found"); return; } t->monitorEnter = 1; t->monitorEnterObject = event->u.monitor.object; t->monitorEnterTime = getMilliticks(); } void Prof::event_monitorContendedEntered( JVMPI_Event* event) { Synchronized sync(dataLock); // cerr << "MONITOR CONTENDED ENTERED: " << (long)(event->env_id) << endl; Thread* t; if (!(t = getThread(event->env_id))) { PROF_ERROR("MONITOR CONTENDED ENTERED", "Thread not found"); return; } if ((!(t->monitorEnter)) || (t->monitorEnterObject != event->u.monitor.object)) { PROF_ERROR("MONITOR CONTENDED ENTERED", "No corresponding MONITOR CONTENDED ENTER"); t->monitorEnter = 0; return; } t->monitorEnter = 0; unsigned long curTime = getMilliticks(); if (curTime < t->monitorEnterTime) return; int numFrames = 1; if (setup.mon.level == Setup::LEVEL_TRACE) numFrames = setup.mon.traceDepth; JVMPI_CallTrace callTrace; JVMPI_CallFrame callFrames[MAX_TRACE]; callTrace.env_id = event->env_id; callTrace.num_frames = (jint)numFrames; callTrace.frames = callFrames; jvmpiInterface->GetCallTrace(&callTrace, (jint)numFrames); numFrames = callTrace.num_frames; if (numFrames == 0) { PROF_ERROR("MONITOR CONTENDED ENTERED", "GetCallTrace failed"); return; } MonStatData* stat; if (setup.mon.threadsEnabled) { if (setup.mon.level == Setup::LEVEL_METHOD) { if (!(stat = getMonThreadMethod(event->env_id, callFrames[0].method_id))) { PROF_ERROR("MONITOR CONTENDED ENTERED", "Cannot get MonThreadMethod"); return; } } else { if (!(stat = getMonThreadTrace(event->env_id, numFrames, callFrames))) { PROF_ERROR("MONITOR CONTENDED ENTERED", "Cannot get MonThreadTrace"); return; } } } else { if (setup.mon.level == Setup::LEVEL_METHOD) { if (!(stat = getMethod(callFrames[0].method_id))) { PROF_ERROR("MONITOR CONTENDED ENTERED", "Method not found"); return; } } else { if (!(stat = getMonTrace(numFrames, callFrames))) { PROF_ERROR("MONITOR CONTENDED ENTERED", "Cannot get MonTrace"); return; } } } int hits = (stat->wait) ? 0 : 1; stat->addMonStat(hits, curTime - t->monitorEnterTime); } void Prof::event_monitorWaited( JVMPI_Event* event) { Synchronized sync(dataLock); // cerr << "MONITOR WAITED: " << (long)(event->env_id) << endl; Thread* t; if (!(t = getThread(event->env_id))) { PROF_ERROR("MONITOR WAITED", "Thread not found"); return; } int numFrames = 1; if (setup.mon.level == Setup::LEVEL_TRACE) numFrames = setup.mon.traceDepth; JVMPI_CallTrace callTrace; JVMPI_CallFrame callFrames[MAX_TRACE]; callTrace.env_id = event->env_id; callTrace.num_frames = (jint)numFrames; callTrace.frames = callFrames; jvmpiInterface->GetCallTrace(&callTrace, (jint)numFrames); numFrames = callTrace.num_frames; if (numFrames == 0) { PROF_ERROR("MONITOR WAITED", "GetCallTrace failed"); return; } MonStatData* stat; if (setup.mon.threadsEnabled) { if (setup.mon.level == Setup::LEVEL_METHOD) { if (!(stat = getMonThreadMethod(event->env_id, callFrames[0].method_id))) { PROF_ERROR("MONITOR WAITED", "Cannot get MonThreadMethod"); return; } } else { if (!(stat = getMonThreadTrace(event->env_id, numFrames, callFrames))) { PROF_ERROR("MONITOR WAITED", "Cannot get MonThreadTrace"); return; } } } else { if (setup.mon.level == Setup::LEVEL_METHOD) { if (!(stat = getMethod(callFrames[0].method_id))) { PROF_ERROR("MONITOR WAITED", "Method not found"); return; } } else { if (!(stat = getMonTrace(numFrames, callFrames))) { PROF_ERROR("MONITOR WAITED", "Cannot get MonTrace"); return; } } } stat->wait = 1; stat->addMonStat(1, event->u.monitor_wait.timeout); } Index: Makefile.rules =================================================================== RCS file: /cvsroot/javaprofiler/library/src/prof/Makefile.rules,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** Makefile.rules 2001/07/22 23:37:58 1.2 --- Makefile.rules 2001/08/24 17:54:04 1.3 *************** *** 38,39 **** --- 38,43 ---- prof_method.obj: prof_method.cpp ../main/includes.h $(CCC) $(CPPFLAGS) prof_method.cpp + + prof_monitor.o \ + prof_monitor.obj: prof_monitor.cpp ../main/includes.h + $(CCC) $(CPPFLAGS) prof_monitor.cpp Index: dir.info =================================================================== RCS file: /cvsroot/javaprofiler/library/src/prof/dir.info,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -r1.4 -r1.5 *** dir.info 2001/07/28 04:11:17 1.4 --- dir.info 2001/08/24 17:54:04 1.5 *************** *** 1,4 **** FILES = prof prof_arena prof_class prof_gc prof_get prof_jniref prof_jvm \ ! prof_method prof_object prof_thread CLEAN_FILES = *.pdb *.obj *.o --- 1,4 ---- FILES = prof prof_arena prof_class prof_gc prof_get prof_jniref prof_jvm \ ! prof_method prof_monitor prof_object prof_thread CLEAN_FILES = *.pdb *.obj *.o Index: prof.cpp =================================================================== RCS file: /cvsroot/javaprofiler/library/src/prof/prof.cpp,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -r1.21 -r1.22 *** prof.cpp 2001/08/23 23:57:31 1.21 --- prof.cpp 2001/08/24 17:54:04 1.22 *************** *** 36,45 **** tF( 19, JVMPI_EVENT_METHOD_ENTRY2, NULL); tF( 20, JVMPI_EVENT_METHOD_EXIT, &Prof::event_methodExit); ! tF( 21, JVMPI_EVENT_MONITOR_CONTENDED_ENTER, NULL); ! tF( 22, JVMPI_EVENT_MONITOR_CONTENDED_ENTERED, NULL); tF( 23, JVMPI_EVENT_MONITOR_CONTENDED_EXIT, NULL); tF( 24, JVMPI_EVENT_MONITOR_DUMP, NULL); tF( 25, JVMPI_EVENT_MONITOR_WAIT, NULL); ! tF( 26, JVMPI_EVENT_MONITOR_WAITED, NULL); tF( 27, JVMPI_EVENT_OBJECT_ALLOC, &Prof::event_objectAlloc); tF( 28, JVMPI_EVENT_OBJECT_DUMP, NULL); --- 36,45 ---- tF( 19, JVMPI_EVENT_METHOD_ENTRY2, NULL); tF( 20, JVMPI_EVENT_METHOD_EXIT, &Prof::event_methodExit); ! tF( 21, JVMPI_EVENT_MONITOR_CONTENDED_ENTER, &Prof::event_monitorContendedEnter); ! tF( 22, JVMPI_EVENT_MONITOR_CONTENDED_ENTERED, &Prof::event_monitorContendedEntered); tF( 23, JVMPI_EVENT_MONITOR_CONTENDED_EXIT, NULL); tF( 24, JVMPI_EVENT_MONITOR_DUMP, NULL); tF( 25, JVMPI_EVENT_MONITOR_WAIT, NULL); ! tF( 26, JVMPI_EVENT_MONITOR_WAITED, &Prof::event_monitorWaited); tF( 27, JVMPI_EVENT_OBJECT_ALLOC, &Prof::event_objectAlloc); tF( 28, JVMPI_EVENT_OBJECT_DUMP, NULL); *************** *** 78,81 **** --- 78,97 ---- prof().shutdownLock.wait(); while( !communThreadEnd) prof().run(); + } + + unsigned long Prof::getMilliticks() { + + #ifdef WIN32 + + return timeGetTime(); + + #else + + struct timeval tv; + + gettimeofday(&tv, NULL); + return (((unsigned long)tv.tv_sec * (unsigned long)1000) + ((unsigned long)tv.tv_usec / (unsigned long)1000)); + + #endif } Index: prof.h =================================================================== RCS file: /cvsroot/javaprofiler/library/src/prof/prof.h,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -r1.31 -r1.32 *** prof.h 2001/08/23 23:57:31 1.31 --- prof.h 2001/08/24 17:54:04 1.32 *************** *** 138,141 **** --- 138,150 ---- Hash<CpuThreadTrace,CpuThreadTraceKey,LI1> activeCpuThreadTraces; + /// hash table of active MonTraces + Hash<MonTrace,TraceKey,LI1> activeMonTraces; + + /// hash table of active MonThreadMethods + Hash<MonThreadMethod,MonThreadMethodKey,LI1> activeMonThreadMethods; + + /// hash table of active MonThreadTraces + Hash<MonThreadTrace,MonThreadTraceKey,LI1> activeMonThreadTraces; + public: *************** *** 366,369 **** --- 375,418 ---- CpuThreadTrace* getCpuThreadTrace(JNIEnv* envId, int numFrames, JVMPI_CallFrame* frames, int create = 1); + /** Returns corresponding MonTrace object. + ** If none exists and the 'create' flag is set to 1 + ** the function attempts to construct one. + ** If unsuccessful in either case the NULL is returned. + ** + ** @param numFrames number of call frames + ** @param frames array of call frames + ** @param create creation flag + ** + ** @return pointer to MonTrace object or NULL */ + + MonTrace* getMonTrace(int numFrames, JVMPI_CallFrame* frames, int create = 1); + + /** Returns corresponding MonThreadMethod object. + ** If none exists and the 'create' flag is set to 1 + ** the function attempts to construct one. + ** If unsuccessful in either case the NULL is returned. + ** + ** @param envId thread ID + ** @param methodId method ID + ** @param create creation flag + ** + ** @return pointer to MonThreadMethod object or NULL */ + + MonThreadMethod* getMonThreadMethod(JNIEnv* envId, jmethodID methodId, int create = 1); + + /** Returns corresponding MonThreadTrace object. + ** If none exists and the 'create' flag is set to 1 + ** the function attempts to construct one. + ** If unsuccessful in either case the NULL is returned. + ** + ** @param envId thread ID + ** @param numFrames number of call frames + ** @param frames array of call frames + ** @param create creation flag + ** + ** @return pointer to MonThreadTrace object or NULL */ + + MonThreadTrace* getMonThreadTrace(JNIEnv* envId, int numFrames, JVMPI_CallFrame* frames, int create = 1); + private: *************** *** 532,535 **** --- 581,632 ---- void event_methodExit ( JVMPI_Event* event); + /** Monitor contended enter. + ** This method is a JVMPI_EVENT_MONITOR_CONTENDED_ENTER + ** event handler. This event is sent when a thread is + ** attemping to enter a Java monitor already acquired + ** by another thread. + ** It is issued with GC disabled. GC is re-enabled after + ** this method returns. + ** Here only the current time before the thread starts + ** waiting on the monitor is recorded. + ** + ** @param event JVMPI_Event structure describing the event + ** + ** @see runEvent(), JVMPI specification */ + + void event_monitorContendedEnter( JVMPI_Event* event); + + /** Monitor contended entered. + ** This method is a JVMPI_EVENT_MONITOR_CONTENDED_ENTERED + ** event handler. This event is sent when a thread enters + ** a Java monitor after waiting for it to be released by + ** another thread. + ** It is issued with GC disabled. GC is re-enabled after + ** this method returns. + ** Here the total time the thread spent by waiting + ** on the monitor is determined and recorded to + ** appriate structures. + ** + ** @param event JVMPI_Event structure describing the event + ** + ** @see runEvent(), JVMPI specification */ + + void event_monitorContendedEntered( JVMPI_Event* event); + + /** Monitor waited. + ** This method is a JVMPI_EVENT_MONITOR_WAITED + ** event handler. This event is sent when a thread + ** finishes waiting on an object. + ** It is issued with GC disabled. GC is re-enabled after + ** this method returns. + ** Here the total time the thread has waited is recored + ** to appropriate structures. + ** + ** @param event JVMPI_Event structure describing the event + ** + ** @see runEvent(), JVMPI specification */ + + void event_monitorWaited( JVMPI_Event* event); + /** Object alloc. This method is a JVMPI_EVENT_OBJECT_ALLOC ** event handler. This event is sent when an object is allocated. *************** *** 819,822 **** --- 916,925 ---- public: + + /** Gets current milliticks. + ** + ** @return ticks in milliseconds */ + + unsigned long getMilliticks(); /** Dumps error. Index: prof_get.cpp =================================================================== RCS file: /cvsroot/javaprofiler/library/src/prof/prof_get.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -r1.5 -r1.6 *** prof_get.cpp 2001/08/04 13:53:37 1.5 --- prof_get.cpp 2001/08/24 17:54:04 1.6 *************** *** 397,399 **** --- 397,492 ---- } + MonTrace* Prof::getMonTrace(int numFrames, JVMPI_CallFrame* frames, int create) { + + TraceKey key; + MonTrace* trace; + + key.numFrames = numFrames; + key.frames = frames; + + if (trace = activeMonTraces.get(key)) return trace; + if (!create) return NULL; + + TraceFrame* traceFrames = TraceFrame::newArray(numFrames); + Method *method; + + for (int i = 0; i < numFrames; i++) { + if (!(method = getMethod(frames[i].method_id))) { + TraceFrame::deleteArray(traceFrames, numFrames); + return NULL; + } + traceFrames[i].method = method; + traceFrames[i].lineno = frames[i].lineno; + } + + trace = new MonTrace; + + trace->method = traceFrames[0].method; + trace->numFrames = numFrames; + trace->frames = traceFrames; + + activeMonTraces.add(trace); + trace->method->monTraces.add(trace); + + return trace; + } + + MonThreadMethod* Prof::getMonThreadMethod(JNIEnv* envId, jmethodID methodId, int create) { + + MonThreadMethodKey key; + MonThreadMethod* threadMethod; + + key.envId = envId; + key.methodId = methodId; + + if (threadMethod = activeMonThreadMethods.get(key)) return threadMethod; + if (!create) return NULL; + + Method* method; + Thread* thread; + + if (!(method = getMethod(methodId))) return NULL; + if (!(thread = getThread(envId))) return NULL; + + threadMethod = new MonThreadMethod; + + threadMethod->method = method; + threadMethod->thread = thread; + + activeMonThreadMethods.add(threadMethod); + method->monThreadMethods.add(threadMethod); + thread->monThreadMethods.add(threadMethod); + + return threadMethod; + } + + MonThreadTrace* Prof::getMonThreadTrace(JNIEnv* envId, int numFrames, JVMPI_CallFrame* frames, int create) { + + MonThreadTraceKey key; + MonThreadTrace* threadTrace; + + key.envId = envId; + key.traceKey.numFrames = numFrames; + key.traceKey.frames = frames; + + if (threadTrace = activeMonThreadTraces.get(key)) return threadTrace; + if (!create) return NULL; + + MonThreadMethod* threadMethod; + MonTrace* trace; + + if (!(threadMethod = getMonThreadMethod(envId, frames[0].method_id))) return NULL; + if (!(trace = getMonTrace(numFrames, frames))) return NULL; + + threadTrace = new MonThreadTrace; + + threadTrace->threadMethod = threadMethod; + threadTrace->trace = trace; + + activeMonThreadTraces.add(threadTrace); + threadMethod->threadTraces.add(threadTrace); + trace->threadTraces.add(threadTrace); + + return threadTrace; + } Index: prof_jvm.cpp =================================================================== RCS file: /cvsroot/javaprofiler/library/src/prof/prof_jvm.cpp,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -r1.18 -r1.19 *** prof_jvm.cpp 2001/08/23 23:57:31 1.18 --- prof_jvm.cpp 2001/08/24 17:54:04 1.19 *************** *** 198,201 **** --- 198,204 ---- long totalCpuThreadMethods = 0; long totalCpuThreadTraces = 0; + long totalMonTraces = 0; + long totalMonThreadMethods = 0; + long totalMonThreadTraces = 0; Class* c = _prof->classes.first(); *************** *** 219,222 **** --- 222,232 ---- } + MonTrace* mt = m->monTraces.first(); + while (mt) { + + totalMonTraces++; + mt = m->monTraces.next(mt); + } + totalMethods++; m = c->methods.next(m); *************** *** 300,303 **** --- 310,327 ---- } + MonThreadMethod* mtm = t->monThreadMethods.first(); + while (mtm) { + + MonThreadTrace* mtt = mtm->threadTraces.first(); + while (mtt) { + + totalMonThreadTraces++; + mtt = mtm->threadTraces.next(mtt); + } + + totalMonThreadMethods++; + mtm = t->monThreadMethods.next(mtm); + } + totalThreads++; t = _prof->threads.next(t); *************** *** 332,335 **** --- 356,366 ---- cout << "CpuTrace: " << totalCpuTraces << endl; cout << "CpuThreadTrace: " << totalCpuThreadTraces << endl; + cout << endl; + + cout << "MonThreadMethod: " << totalMonThreadMethods << endl; + cout << endl; + + cout << "MonTrace: " << totalMonTraces << endl; + cout << "MonThreadTrace: " << totalMonThreadTraces << endl; cout << endl; } |