Re: Enhancements to nprof
Thomas Strauß <[email protected]> Tue, 28 Dec 2004 09:21:48 +0100
| Newsgroups | gmane.comp.windows.dotnet.nprof.devel |
|---|---|
| Message-ID | <[email protected]> |
--=====================_51187533==_ Content-Type: text/plain; charset="us-ascii"; format=flowed Hi Matthew, Please have a look at my changes. The main change is the creation of an tcp-connection from the profiler to the profilee. This connection allows to toggle the capture behaviour. The overall structure of the profiler-hook was not changed. There are only some saves in the hashmap lookups. The Glue was adapted to the changes in the hook. In the GUI a menu item was added. The name is not perfect. Please feel free to give it a better name. The UI also suppresses threads with no times taken. If you have more questions please don't hesitate to ask. Cheers Thomas At 02:58 28.12.2004, you wrote: >Excellent. Can you send me a patch in "unified diff" format to review? >I'd like to take a look before committing it, but I imagine we can get it >in there ASAP. > >[email protected] wrote: > >>Hi, >> >>i was extending nprof to be able to switch on/off the sampling in the >>profiler. Is there a way to put this to the archive? >> >>Thanks and best regards >> >>Thomas --=====================_51187533==_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: attachment; filename="nprof.patch" Index: NProf.Hook/functioninfo.cpp =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/functioninfo.cpp,v retrieving revision 1.2 diff -u -w -b -r1.2 functioninfo.cpp --- NProf.Hook/functioninfo.cpp 27 Dec 2003 21:10:42 -0000 1.2 +++ NProf.Hook/functioninfo.cpp 22 Dec 2004 19:48:14 -0000 @@ -34,14 +34,15 @@ CalleeFunctionInfo* FunctionInfo::GetCalleeFunctionInfo( FunctionID fid ) { - if ( _mCalleeInfo.find( fid ) == _mCalleeInfo.end() ) + map< FunctionID, CalleeFunctionInfo* >::const_iterator result = _mCalleeInfo.find( fid ); + if ( result == _mCalleeInfo.end() ) { CalleeFunctionInfo* pFunctionInfo = new CalleeFunctionInfo(); - _mCalleeInfo.insert( make_pair( fid, pFunctionInfo ) ); + _mCalleeInfo[fid] = pFunctionInfo; return pFunctionInfo; } - return _mCalleeInfo[ fid ]; + return result->second; } /** No descriptions */ Index: NProf.Hook/profiler.cpp =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/profiler.cpp,v retrieving revision 1.3 diff -u -w -b -r1.3 profiler.cpp --- NProf.Hook/profiler.cpp 27 Dec 2003 21:10:42 -0000 1.3 +++ NProf.Hook/profiler.cpp 22 Dec 2004 12:16:26 -0000 @@ -23,6 +23,7 @@ { _pPrfInfo = pPrfInfo; _phHelper.Initialize( _pPrfInfo ); + instance = this; } Profiler::~Profiler() @@ -32,8 +33,9 @@ /** No descriptions */ void Profiler::Enter( FunctionID fid ) { - FunctionInfo* pFunctionInfo = GetCurrentThreadInfo()->GetFunctionInfo( fid ); - GetCurrentThreadInfo()->GetStackInfo()->PushFunction( pFunctionInfo, rdtsc() ); + ThreadInfo *currentThreadInfo = GetCurrentThreadInfo(); + FunctionInfo* pFunctionInfo = currentThreadInfo->GetFunctionInfo( fid ); + currentThreadInfo->GetStackInfo()->PushFunction( pFunctionInfo, rdtsc() ); } /** No descriptions */ @@ -50,8 +52,9 @@ void Profiler::UnmanagedToManagedCall( FunctionID fid ) { - FunctionInfo* pFunctionInfo = GetCurrentThreadInfo()->GetFunctionInfo( fid ); - GetCurrentThreadInfo()->GetStackInfo()->PushFunction( pFunctionInfo, rdtsc() ); + ThreadInfo *currentThreadInfo = GetCurrentThreadInfo(); + FunctionInfo* pFunctionInfo = currentThreadInfo->GetFunctionInfo( fid ); + currentThreadInfo->GetStackInfo()->PushFunction( pFunctionInfo, rdtsc() ); } void Profiler::ManagedToUnmanagedCall( FunctionID fid ) @@ -129,3 +132,14 @@ { _tic.Trace( _phHelper ); } +/** No descriptions */ + +void Profiler::Enable(bool enabled) +{ + Profiler::enabled = enabled; + instance->_tic.EnableProfiler(enabled); +} + +bool Profiler::enabled = false; + +Profiler *Profiler::instance = 0; Index: NProf.Hook/profiler.h =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/profiler.h,v retrieving revision 1.1.1.1 diff -u -w -b -r1.1.1.1 profiler.h --- NProf.Hook/profiler.h 9 Mar 2003 20:37:29 -0000 1.1.1.1 +++ NProf.Hook/profiler.h 21 Dec 2004 12:18:22 -0000 @@ -46,13 +46,17 @@ void AppDomainEnd( AppDomainID aid ); void End(); void ThreadMap( ThreadID tid, DWORD dwOSThread ); + static void Enable(bool enabled); /** No descriptions */ void Trace(); + static bool enabled; private: ThreadID GetCurrentThreadID(); ThreadInfo* GetCurrentThreadInfo(); + static Profiler* instance; + ThreadInfoCollection _tic; CComPtr< ICorProfilerInfo > _pPrfInfo; ProfilerHelper _phHelper; Index: NProf.Hook/profiler_helper.h =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/profiler_helper.h,v retrieving revision 1.1.1.1 diff -u -w -b -r1.1.1.1 profiler_helper.h --- NProf.Hook/profiler_helper.h 9 Mar 2003 20:37:29 -0000 1.1.1.1 +++ NProf.Hook/profiler_helper.h 22 Dec 2004 23:03:22 -0000 @@ -29,3 +29,4 @@ char *buffer ); CComPtr< ICorProfilerInfo > _pPrfInfo; }; + Index: NProf.Hook/profiler_socket.cpp =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/profiler_socket.cpp,v retrieving revision 1.5 diff -u -w -b -r1.5 profiler_socket.cpp --- NProf.Hook/profiler_socket.cpp 2 Jul 2004 22:16:58 -0000 1.5 +++ NProf.Hook/profiler_socket.cpp 20 Dec 2004 08:13:12 -0000 @@ -1,5 +1,7 @@ #include "stdafx.h" #include "profiler_socket.h" +#include "profiler.h" +#include <process.h> #define SAFE_SEND( socket, data ) \ { \ @@ -39,6 +41,98 @@ bool ProfilerSocket::_bInitialized = false; int ProfilerSocket::_nApplicationID = -1; +class MessageReceiver { +public: + MessageReceiver() { + cout << "MessageReceiver " << endl; + _s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if ( _s == INVALID_SOCKET ) { + HandleError( "WSASocket", WSAGetLastError() ); + } else { + + name.sin_family = AF_INET; + name.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +// name.sin_port = htons(12346); + name.sin_port = htons(0); + + int on = 1; + setsockopt( _s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, + sizeof(on) ); + + if ( bind( _s, (SOCKADDR*) &name, sizeof(name) ) == SOCKET_ERROR ) { + printf( "bind() failed.\n" ); + closesocket(_s); + _s = INVALID_SOCKET; + return; + } + int len = sizeof(name); + + getsockname(_s, (SOCKADDR*) &name, &len); + + // Listen on the Socket. + if ( listen( _s, 1 ) == SOCKET_ERROR ) { + printf( "Error listening on socket.\n"); + closesocket(_s); + _s = INVALID_SOCKET; + return; + } + + cout << "server on port = " << GetPort() << endl; + + _beginthread(MessageReceiverCallback, 0,(void *) this); + + return; + + } + + _s = INVALID_SOCKET; + } + int GetPort() { + return ntohs(name.sin_port); + } +private: + SOCKET _s; + sockaddr_in name; + void HandleError( const char* szCaller, int nError ) { + cout << "error : " << nError << endl; + } + void HandleWrongRecvLength( const char* szCaller, int nExpected, int nSent ) { + } + static void MessageReceiverCallback(void *instance) { + MessageReceiver *receiver = (MessageReceiver *) instance; + while (true) { + cout << " accept " << endl; + SOCKET s = accept(receiver->_s, 0, 0); + cout << "MessageReceiverCallback() " << endl; + if (s == INVALID_SOCKET) { + receiver->HandleError("Error in MessageReceiverCallback() : ", WSAGetLastError()); + } + BYTE b; + if (((MessageReceiver *) instance)->ReadByte(s, b) == 0) { + if (b == 42) { + Profiler::Enable(true); + cout << "Enabled" << endl; + } + + if (b == 43) { + Profiler::Enable(false); + cout << "Disabled" << endl; + } + } + closesocket(s); + } + } + int ReadByte( SOCKET &s, BYTE& b ) { + int result; + SAFE_READ( s, b, result ); + + return result; + } + +}; + +MessageReceiver *ProfilerSocket::receiver = 0; + ProfilerSocket::ProfilerSocket() { _szOperation = "ctor"; @@ -84,9 +178,13 @@ cout << "WSAStartup: " << WSAGetLastError() << endl; cout << "port = " << atoi( getenv( "NPROF_PROFILING_SOCKET" ) ) << endl; ProfilerSocket ps; + if (ProfilerSocket::receiver == 0) { + ProfilerSocket::receiver = new MessageReceiver(); + } ps.SendInitialize(); } + void ProfilerSocket::SendInitialize() { _szOperation = "SendInitialize"; @@ -108,6 +206,10 @@ ReadByte( b ); _nApplicationID = b; + cout << "Listen on port = " << receiver->GetPort() << endl; + + SendUINT32( receiver->GetPort() ); + cout << "Application ID = " << _nApplicationID << endl; SendUINT32( ::GetCurrentProcessId() ); Index: NProf.Hook/profiler_socket.h =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/profiler_socket.h,v retrieving revision 1.4 diff -u -w -b -r1.4 profiler_socket.h --- NProf.Hook/profiler_socket.h 2 Jul 2004 22:16:58 -0000 1.4 +++ NProf.Hook/profiler_socket.h 17 Dec 2004 11:59:40 -0000 @@ -16,6 +16,8 @@ const int NETWORK_PROTOCOL_VERSION = 3; +class MessageReceiver; + class ProfilerSocket { public: @@ -48,7 +50,6 @@ inline void SendAppDomainID( AppDomainID aid ); inline void SendThreadID( ThreadID tid ); inline void SendFunctionID( FunctionID fid ); - private: SOCKET _s; const char* _szOperation; @@ -56,4 +57,7 @@ static bool _bInitialized; static int _nApplicationID; + + static MessageReceiver *receiver; + }; Index: NProf.Hook/stackinfo.cpp =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/stackinfo.cpp,v retrieving revision 1.2 diff -u -w -b -r1.2 stackinfo.cpp --- NProf.Hook/stackinfo.cpp 27 Dec 2003 21:10:42 -0000 1.2 +++ NProf.Hook/stackinfo.cpp 22 Dec 2004 12:45:32 -0000 @@ -18,6 +18,7 @@ #include "stdafx.h" #include "stackinfo.h" #include "threadinfo.h" +#include "profiler.h" StackInfo::StackInfo( ThreadInfo* pThreadInfo ) { @@ -31,7 +32,7 @@ /** No descriptions */ void StackInfo::PushFunction( FunctionInfo* pFunctionInfo, INT64 llCycleCount ) { - if ( _sFunctionStack.size() > 0 ) + if ( !_sFunctionStack.empty()) { // Increment the recursive count of this callee function info so we don't double-book entries FunctionInfo* pCallerFunctionInfo = _sFunctionStack.top().pFunctionInfo; @@ -39,12 +40,16 @@ CalleeFunctionInfo* pCalleeFunctionInfo = pCallerFunctionInfo->GetCalleeFunctionInfo( fidCallee ); pCalleeFunctionInfo->nRecursiveCount++; + if (Profiler::enabled) { pCalleeFunctionInfo->nCalls++; } + } // Increment the recursive count of this function info so we don't double-book entries pFunctionInfo->nRecursiveCount++; + if (Profiler::enabled) { pFunctionInfo->nCalls++; + } _sFunctionStack.push( StackEntryInfo( pFunctionInfo, llCycleCount ) ); } @@ -52,33 +57,44 @@ /** No descriptions */ INT64 StackInfo::PopFunction( INT64 llCycleCount ) { - INT64 llElapsed = llCycleCount - _sFunctionStack.top().llCycleStart; - FunctionInfo* pFunctionInfo = _sFunctionStack.top().pFunctionInfo; + StackEntryInfo stackEntry = _sFunctionStack.top(); + INT64 llElapsed = llCycleCount - stackEntry.llCycleStart; + FunctionInfo* pFunctionInfo = stackEntry.pFunctionInfo; FunctionID fidCallee = pFunctionInfo->fid; // Only add the time if we're at the lowest call to the function on the stack // Prevents double-accounting of recursive functions pFunctionInfo->nRecursiveCount--; - if ( pFunctionInfo->nRecursiveCount == 0 ) + if ( pFunctionInfo->nRecursiveCount == 0 ) { + if (Profiler::enabled) { pFunctionInfo->llCycleCount += llElapsed; - else + } + } else { + if (Profiler::enabled) { pFunctionInfo->llRecursiveCycleCount += llElapsed; + } + } _sFunctionStack.pop(); - if ( _sFunctionStack.size() > 0 ) + if ( !_sFunctionStack.empty()) { CalleeFunctionInfo* pCalleeFunctionInfo = _sFunctionStack.top().pFunctionInfo->GetCalleeFunctionInfo( fidCallee ); // Only add the time if we're at the lowest call to the function on the stack // Prevents double-accounting of recursive functions pCalleeFunctionInfo->nRecursiveCount--; - if ( pCalleeFunctionInfo->nRecursiveCount == 0 ) + if ( pCalleeFunctionInfo->nRecursiveCount == 0 ) { + if (Profiler::enabled) { pCalleeFunctionInfo->llCycleCount += llElapsed; - else + } + } else { + if (Profiler::enabled) { pCalleeFunctionInfo->llRecursiveCycleCount += llElapsed; } + } + } return llElapsed; } @@ -87,11 +103,11 @@ void StackInfo::SuspendFunction( INT64 llCycleCount ) { _llSuspendStart = llCycleCount; - if ( _sFunctionStack.size() == 0 ) - { - cout << "Suspend with no call stack!" << endl; - return; - } +// if ( _sFunctionStack.empty() ) +// { +// cout << "Suspend with no call stack!" << endl; +// return; +// } //cout << "Suspended function ID: " << _sFunctionStack.top().pFunctionInfo->fid << endl; } @@ -100,7 +116,7 @@ { INT64 llElapsed = llCycleCount - _llSuspendStart; // Resume with no call stack, ignore - if ( _sFunctionStack.size() == 0 ) + if ( _sFunctionStack.empty() ) { cout << "Resume with no call stack!" << endl; return; Index: NProf.Hook/threadinfo.cpp =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/threadinfo.cpp,v retrieving revision 1.2 diff -u -w -b -r1.2 threadinfo.cpp --- NProf.Hook/threadinfo.cpp 27 Dec 2003 21:10:42 -0000 1.2 +++ NProf.Hook/threadinfo.cpp 22 Dec 2004 12:42:46 -0000 @@ -18,11 +18,14 @@ #include "stdafx.h" #include "threadinfo.h" #include "profiler_socket.h" +#include "profiler.h" -ThreadInfo::ThreadInfo() +ThreadInfo::ThreadInfo(ThreadID tid) { _bRunning = false; _llSuspendTime = 0; + _llElapsed = 0; + _tid = tid; _pStackInfo = new StackInfo( this ); } @@ -31,6 +34,18 @@ delete _pStackInfo; } +void ThreadInfo::EnableProfiler(bool enabled) { + INT64 time = rdtsc(); + if (enabled) { + _llStartTime = time; + } else { + _llElapsed += (time - _llStartTime); + _llEndTime = time; + _llStartTime = time - _llElapsed; + } +} + + void ThreadInfo::Start() { _llStartTime = rdtsc(); @@ -39,7 +54,10 @@ void ThreadInfo::End() { + if (Profiler::enabled) { _llEndTime = rdtsc(); + _llStartTime -= _llElapsed; + } _bRunning = false; } @@ -48,21 +66,17 @@ return _bRunning; } -StackInfo* ThreadInfo::GetStackInfo() -{ - return _pStackInfo; -} - FunctionInfo* ThreadInfo::GetFunctionInfo( FunctionID fid ) { - if ( _mFunctionInfo.find( fid ) == _mFunctionInfo.end() ) + map< FunctionID, FunctionInfo* >::const_iterator result = _mFunctionInfo.find( fid ); + if ( result == _mFunctionInfo.end() ) { FunctionInfo* pFunctionInfo = new FunctionInfo( fid ); - _mFunctionInfo.insert( make_pair( fid, pFunctionInfo ) ); + _mFunctionInfo[fid] = pFunctionInfo; return pFunctionInfo; } - return _mFunctionInfo[ fid ]; + return result->second; } /** No descriptions */ Index: NProf.Hook/threadinfo.h =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/threadinfo.h,v retrieving revision 1.2 diff -u -w -b -r1.2 threadinfo.h --- NProf.Hook/threadinfo.h 27 Dec 2003 21:10:42 -0000 1.2 +++ NProf.Hook/threadinfo.h 22 Dec 2004 12:12:18 -0000 @@ -31,24 +31,29 @@ class ThreadInfo { public: - ThreadInfo(); + ThreadInfo(ThreadID tid); ~ThreadInfo(); void Start(); void End(); + void EnableProfiler(bool enabled); bool IsRunning(); - StackInfo* GetStackInfo(); + StackInfo* GetStackInfo() { + return _pStackInfo; + } FunctionInfo* GetFunctionInfo( FunctionID fid ); void Trace( ProfilerHelper& ph ); void Dump( ProfilerSocket& ps, ProfilerHelper& ph ); INT64 _llStartTime; INT64 _llEndTime; INT64 _llSuspendTime; + ThreadID _tid; private: bool _bRunning; StackInfo* _pStackInfo; map< FunctionID, FunctionInfo* > _mFunctionInfo; + INT64 _llElapsed; }; #endif Index: NProf.Hook/threadinfocollection.cpp =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/threadinfocollection.cpp,v retrieving revision 1.1.1.1 diff -u -w -b -r1.1.1.1 threadinfocollection.cpp --- NProf.Hook/threadinfocollection.cpp 9 Mar 2003 20:37:30 -0000 1.1.1.1 +++ NProf.Hook/threadinfocollection.cpp 22 Dec 2004 12:42:46 -0000 @@ -20,6 +20,7 @@ ThreadInfoCollection::ThreadInfoCollection() { + lastThreadInfo = 0; } ThreadInfoCollection::~ThreadInfoCollection() @@ -44,14 +45,18 @@ ThreadInfo* ThreadInfoCollection::GetThreadInfo( ThreadID tid ) { - if ( _mThreadInfo.find( tid ) == _mThreadInfo.end() ) + if (lastThreadInfo != 0 && lastThreadInfo->_tid == tid) { + return lastThreadInfo; + } + map< ThreadID, ThreadInfo* >::const_iterator result = _mThreadInfo.find( tid ); + if ( result == _mThreadInfo.end() ) { - ThreadInfo* pThreadInfo = new ThreadInfo(); - _mThreadInfo.insert( make_pair( tid, pThreadInfo ) ); - return pThreadInfo; + lastThreadInfo = new ThreadInfo(tid); + _mThreadInfo[tid] = lastThreadInfo; + } else { + lastThreadInfo = result->second; } - - return _mThreadInfo[ tid ]; + return lastThreadInfo; } /** No descriptions */ @@ -78,6 +83,13 @@ } } +void ThreadInfoCollection::EnableProfiler(bool enabled) { + for ( map< ThreadID, ThreadInfo* >::iterator it = _mThreadInfo.begin(); it != _mThreadInfo.end(); it++ ) + { + it->second->EnableProfiler(enabled); + } +} + void ThreadInfoCollection::Dump( ProfilerHelper& ph, ThreadID tid ) { ProfilerSocket ps; Index: NProf.Hook/threadinfocollection.h =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Hook/threadinfocollection.h,v retrieving revision 1.1.1.1 diff -u -w -b -r1.1.1.1 threadinfocollection.h --- NProf.Hook/threadinfocollection.h 9 Mar 2003 20:37:30 -0000 1.1.1.1 +++ NProf.Hook/threadinfocollection.h 22 Dec 2004 12:10:56 -0000 @@ -41,8 +41,10 @@ void DumpAll( ProfilerHelper& ph ); void Dump( ProfilerHelper& ph, ThreadID tid ); void Trace( ProfilerHelper& ph ); + void EnableProfiler(bool enabled); private: map< ThreadID, ThreadInfo* > _mThreadInfo; + ThreadInfo *lastThreadInfo; }; #endif Index: NProf.Glue/Profiler/Info/FunctionInfoCollection.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Glue/Profiler/Info/FunctionInfoCollection.cs,v retrieving revision 1.2 diff -u -w -b -r1.2 FunctionInfoCollection.cs --- NProf.Glue/Profiler/Info/FunctionInfoCollection.cs 2 Jul 2004 22:16:57 -0000 1.2 +++ NProf.Glue/Profiler/Info/FunctionInfoCollection.cs 20 Dec 2004 08:53:52 -0000 @@ -35,5 +35,11 @@ } Hashtable _htFunctionInfo; + + public int Count { + get { + return _htFunctionInfo.Count; + } + } } } Index: NProf.Glue/Profiler/Info/ProcessInfo.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Glue/Profiler/Info/ProcessInfo.cs,v retrieving revision 1.1 diff -u -w -b -r1.1 ProcessInfo.cs --- NProf.Glue/Profiler/Info/ProcessInfo.cs 2 Jul 2004 22:16:57 -0000 1.1 +++ NProf.Glue/Profiler/Info/ProcessInfo.cs 21 Dec 2004 07:07:00 -0000 @@ -32,12 +32,16 @@ set { _nProcessID = value; } } - public string Name - { + public string Name { get { return _strName; } set { _strName = value; } } + public int Port { + get { return _port; } + set { _port = value; } + } + public FunctionSignatureMap Functions { get { return _fsm; } @@ -50,6 +54,15 @@ set { _tic = value; } } + public bool Completed { + get { + return _completed; + } + set { + _completed = value; + } + } + public override string ToString() { return String.Format( "{0} ({1})", _strName, _nProcessID ); @@ -57,8 +70,10 @@ private int _nID; private int _nProcessID; + private int _port; private FunctionSignatureMap _fsm; private ThreadInfoCollection _tic; private string _strName; + private bool _completed; } } Index: NProf.GUI/ProcessTree.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.GUI/ProcessTree.cs,v retrieving revision 1.1 diff -u -w -b -r1.1 ProcessTree.cs --- NProf.GUI/ProcessTree.cs 2 Jul 2004 22:16:55 -0000 1.1 +++ NProf.GUI/ProcessTree.cs 20 Dec 2004 08:53:52 -0000 @@ -62,21 +62,21 @@ tnProcess.SelectedImageIndex = 0; tnProcess.Tag = pi; - foreach ( ThreadInfo ti in pi.Threads ) - { + foreach ( ThreadInfo ti in pi.Threads ) { + if (ti.FunctionInfoCollection.Count != 0) { TreeNode tnThread = tnProcess.Nodes.Add( ti.ToString() ); tnThread.ImageIndex = 1; tnThread.SelectedImageIndex = 1; tnThread.Tag = ti; - if ( bFirst ) - { + if ( bFirst ) { _tvProcess.SelectedNode = tnThread; bFirst = false; } } } } + } #region Component Designer generated code /// <summary> Index: NProf.GUI/ProfilerControl.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.GUI/ProfilerControl.cs,v retrieving revision 1.16 diff -u -w -b -r1.16 ProfilerControl.cs --- NProf.GUI/ProfilerControl.cs 22 Sep 2004 15:35:43 -0000 1.16 +++ NProf.GUI/ProfilerControl.cs 20 Dec 2004 08:59:14 -0000 @@ -563,6 +563,9 @@ tnRoot.Checked = true; ThreadInfo tiCurrentThread = _tiCurrent; + if (tiCurrentThread == null) { + return; + } foreach ( FunctionInfo fi in tiCurrentThread.FunctionInfoCollection ) { TreeNodeCollection tnc = tnRoot.Nodes; @@ -616,6 +619,9 @@ _lvFunctionInfo.BeginUpdate(); ThreadInfo tiCurrentThread = _tiCurrent; + if (tiCurrentThread == null) { + return; + } foreach ( FunctionInfo fi in tiCurrentThread.FunctionInfoCollection ) { if ( !htNamespaces.Contains( fi.Signature.NamespaceString ) ) Index: NProf.GUI/ProfilerForm.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.GUI/ProfilerForm.cs,v retrieving revision 1.28 diff -u -w -b -r1.28 ProfilerForm.cs --- NProf.GUI/ProfilerForm.cs 3 Oct 2004 15:58:42 -0000 1.28 +++ NProf.GUI/ProfilerForm.cs 22 Dec 2004 10:19:42 -0000 @@ -64,6 +64,8 @@ private Reflector.UserInterface.CommandBarManager commandBarManager1; private Reflector.UserInterface.CommandBar commandBar1; private Reflector.UserInterface.CommandBar commandBar2; + private Crownwood.Magic.Menus.MenuCommand _sep5; + private Crownwood.Magic.Menus.MenuCommand _cmdProjectEnabled; /// <summary> /// Required designer variable. @@ -83,6 +85,7 @@ _stackBack = new Stack(); _stackForward = new Stack(); _p = new Profiler(); + ProfilerEnabled = false; //_p.ProcessCompleted += new Profiler.ProcessCompletedHandler( OnProfileComplete ); _p.Error += new Profiler.ErrorHandler( OnError ); _piInitialProject = null; @@ -150,6 +153,8 @@ this._sbpMessage = new System.Windows.Forms.StatusBarPanel(); this.commandBarManager1 = new Reflector.UserInterface.CommandBarManager(); this.commandBar1 = new Reflector.UserInterface.CommandBar(); + this._sep5 = new Crownwood.Magic.Menus.MenuCommand(); + this._cmdProjectEnabled = new Crownwood.Magic.Menus.MenuCommand(); ((System.ComponentModel.ISupportInitialize)(this._sbpMessage)).BeginInit(); this.SuspendLayout(); // @@ -280,7 +285,9 @@ this._cmdProjectOptions, this._sep4, this._cmdProjectRunViewMessages, - this._cmdProjectRunCopy}); + this._cmdProjectRunCopy, + this._sep5, + this._cmdProjectEnabled}); this._menuProject.Text = "&Project"; // // _cmdProjectRun @@ -409,6 +416,18 @@ this.commandBar1.TabStop = false; this.commandBar1.Text = "commandBar1"; // + // _sep5 + // + this._sep5.Description = "-"; + this._sep5.Text = "-"; + // + // _cmdProjectEnabled + // + this._cmdProjectEnabled.Checked = true; + this._cmdProjectEnabled.Description = "MenuItem"; + this._cmdProjectEnabled.Text = "Enabled"; + this._cmdProjectEnabled.Click += new System.EventHandler(this._cmdProjectEnabled_Click); + // // ProfilerForm // this.AllowDrop = true; @@ -536,13 +555,12 @@ commandBarManager1.CommandBars.Add( commandBar2 ); _pic = new ProjectInfoCollection(); - _pt = new ProjectTree(); + _pt = new ProjectTree(this); _pic.ProjectRemoved +=new NProf.Glue.Profiler.Project.ProjectInfoCollection.ProjectEventHandler(_pic_ProjectRemoved); _pt.Projects = _pic; _pt.ProjectDoubleClicked += new ProjectTree.ProjectDoubleClickedHandler( _pt_ProjectDoubleClicked ); - _pt.RunDoubleClicked += new ProjectTree.RunDoubleClickedHandler( _pt_RunDoubleClicked ); _pt.ExecutablesDropped +=new ProjectTree.ExecutablesDroppedHandler( _pt_ExecutableDropped ); _dock = new Crownwood.Magic.Docking.DockingManager( this, Crownwood.Magic.Common.VisualStyle.IDE ); @@ -974,6 +992,32 @@ _cmdViewNavForward.Enabled = ( !IsShowingBlankTab() ); } + private void _cmdProjectEnabled_Click(object sender, System.EventArgs e) { + ProfilerEnabled = !ProfilerEnabled; + } + + private bool ProfilerEnabled { + set { + _p.EnableProfiler = value; + _cmdProjectEnabled.Checked = value; + } + get { + return _cmdProjectEnabled.Checked; + } + } + + public Run ActiveRun { + set { + foreach (Crownwood.Magic.Controls.TabPage tp in _tcProfilers.TabPages) { + if (tp.Tag.Equals(value)) { + int index = _tcProfilers.TabPages.IndexOf(tp); + _tcProfilers.SelectedIndex = index; + break; + } + } + } + } + private class Images { private static Image[] images = null; Index: NProf.GUI/ProjectTree.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.GUI/ProjectTree.cs,v retrieving revision 1.9 diff -u -w -b -r1.9 ProjectTree.cs --- NProf.GUI/ProjectTree.cs 2 Jul 2004 22:16:55 -0000 1.9 +++ NProf.GUI/ProjectTree.cs 22 Dec 2004 10:24:12 -0000 @@ -16,18 +16,19 @@ public class ProjectTree : System.Windows.Forms.UserControl { private System.Windows.Forms.TreeView _tvProjects; - private System.ComponentModel.IContainer components; private System.Windows.Forms.ImageList _ilState; + private ProfilerForm _form; private ProjectInfoCollection _pic; - public ProjectTree() + public ProjectTree(ProfilerForm form) { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); // TODO: Add any initialization after the InitForm call _pic = null; + _form = form; } /// <summary> @@ -37,10 +38,6 @@ { if( disposing ) { - if(components != null) - { - components.Dispose(); - } } base.Dispose( disposing ); } @@ -75,6 +72,7 @@ this.Controls.Add(this._tvProjects); this.Name = "ProjectTree"; this.Size = new System.Drawing.Size(344, 464); + this.Click += new System.EventHandler(this.ProjectTree_Click); this.Load += new System.EventHandler(this.ProjectTree_Load); this.ResumeLayout(false); @@ -312,6 +310,13 @@ ExecutablesDropped.BeginInvoke( files, null, null ); } + private void ProjectTree_Click(object sender, System.EventArgs e) { + Run _run = _tvProjects.SelectedNode.Tag as Run; + if (_run != null) { + _form.ActiveRun = _run; + } + } + public event ProjectDoubleClickedHandler ProjectDoubleClicked; public event RunDoubleClickedHandler RunDoubleClicked; public event ExecutablesDroppedHandler ExecutablesDropped; Index: NProf.Glue/Profiler/Profiler.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Glue/Profiler/Profiler.cs,v retrieving revision 1.16 diff -u -w -b -r1.16 Profiler.cs --- NProf.Glue/Profiler/Profiler.cs 2 Jul 2004 22:16:56 -0000 1.16 +++ NProf.Glue/Profiler/Profiler.cs 17 Dec 2004 14:59:02 -0000 @@ -44,6 +44,15 @@ return true; } + public bool EnableProfiler { + set { + if (_pss != null) { + _pss.EnableProfiler = value; + } + enabled = value; + } + } + public bool Start( ProjectInfo pi, Run run, ProcessCompletedHandler pch ) { _dtStart = DateTime.Now; @@ -53,10 +62,10 @@ _run.State = Run.RunState.Initializing; _pss = new ProfilerSocketServer( pi.Options, run ); + _pss.EnableProfiler = enabled; _pss.Start(); _pss.Exited += new EventHandler( OnProcessExited ); _pss.Error += new ProfilerSocketServer.ErrorHandler( OnError ); - _pss.Message += new ProfilerSocketServer.MessageHandler( OnMessage ); switch ( pi.ProjectType ) { @@ -71,7 +80,6 @@ _p.StartInfo.Arguments = pi.Arguments; _p.StartInfo.WorkingDirectory = pi.WorkingDirectory; _p.EnableRaisingEvents = true; - //_p.Exited += new EventHandler( OnProcessExited ); return _p.Start(); } @@ -281,7 +289,6 @@ } public delegate void ProcessCompletedHandler( Run run ); - public event ProcessCompletedHandler ProcessCompleted; public delegate void ErrorHandler( Exception e ); public event ErrorHandler Error; public delegate void MessageHandler( string strMessage ); @@ -300,5 +307,6 @@ private Process _p; private ProjectInfo _pi; private ProfilerSocketServer _pss; + private bool enabled; } } Index: NProf.Glue/Profiler/Core/ProfilerSocketServer.cs =================================================================== RCS file: /cvsroot/nprof/nprof/NProf.Glue/Profiler/Core/ProfilerSocketServer.cs,v retrieving revision 1.10 diff -u -w -b -r1.10 ProfilerSocketServer.cs --- NProf.Glue/Profiler/Core/ProfilerSocketServer.cs 2 Jul 2004 22:16:56 -0000 1.10 +++ NProf.Glue/Profiler/Core/ProfilerSocketServer.cs 21 Dec 2004 07:07:00 -0000 @@ -30,6 +30,7 @@ public void Start() { _t = new Thread( new ThreadStart( ListenThread ) ); + _t.IsBackground = true; _mreStarted = new ManualResetEvent( false ); _t.Start(); _mreStarted.WaitOne(); @@ -40,6 +41,7 @@ lock ( _s ) Interlocked.Increment( ref _nStopFlag ); _s.Close(); + _s = null; } public bool HasStoppedGracefully @@ -50,19 +52,16 @@ private void ListenThread() { Thread.CurrentThread.Name = "ProfilerSocketServer Listen Thread"; - try - { + try { _mreReceivedMessage = new ManualResetEvent( false ); - using ( _s = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ) ) - { + using ( _s = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ) ) { IPEndPoint ep = new IPEndPoint( IPAddress.Loopback, 0 ); _s.Bind( ep ); _nPort = ( ( IPEndPoint )_s.LocalEndPoint ).Port; _mreStarted.Set(); _s.Listen( 100 ); - while ( true ) - { + while ( true ) { _mreReceivedMessage.Reset(); lock ( _s ) if ( _nStopFlag == 1 ) @@ -72,12 +71,43 @@ } } } - catch ( Exception e ) - { + catch ( Exception) { _mreStarted.Set(); } } + public bool EnableProfiler { + set { + _profilerEnabled = value; + if (_s != null) { + SendEnabled(); + } + } + } + + private void SendEnabled() { + foreach (ProcessInfo processInfo in _run.Processes) { + if (processInfo != null && !processInfo.Completed) { + try { + IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, processInfo.Port); + Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + s.Connect(ep); + NetworkStream ns = new NetworkStream(s, true); + if (_profilerEnabled) { + ns.WriteByte(42); + } else { + ns.WriteByte(43); + } + s.Close(); + } catch (Exception e) { + _run.Messages.AddMessage( "Port: " + processInfo.Port ); + _run.Messages.AddMessage( "ProcessID: " + processInfo.ID ); + _run.Messages.AddMessage( "Exception: " + e ); + } + } + } + } + private string ReadLengthEncodedASCIIString( BinaryReader br ) { int nLength = br.ReadInt32(); @@ -191,6 +221,9 @@ ns.WriteByte( ( byte )nApplicationID ); + piCurrent.Port = ( int )br.ReadUInt32(); + _run.Messages.AddMessage( "port: " + piCurrent.Port); + piCurrent.ProcessID = ( int )br.ReadUInt32(); int nArgs = ( int )br.ReadUInt32(); @@ -210,6 +243,7 @@ _nProfileCount++; _run.Messages.AddMessage( "Connected to " + piCurrent.Name + " with process ID " + piCurrent.ProcessID ); + SendEnabled(); } // We're off! @@ -222,6 +256,8 @@ _nProfileCount--; _run.Messages.AddMessage( "Profiling completed for " + piCurrent.Name ); + piCurrent.Completed = true; + if ( _nProfileCount == 0 ) { _bHasStopped = true; @@ -296,7 +332,9 @@ CalleeFunctionInfo[] acfi = ( CalleeFunctionInfo[] )alCallees.ToArray( typeof( CalleeFunctionInfo ) ); FunctionInfo fi = new FunctionInfo( piCurrent.Threads[ nThreadID ], nFunctionID, fs, nCalls, lTotalTime, lTotalRecursiveTime, lTotalSuspendTime, acfi ); + if (fi.Calls != 0) { piCurrent.Threads[ nThreadID ].FunctionInfoCollection.Add( fi ); + } nFunctionID = br.ReadInt32(); nIndex++; @@ -328,7 +366,6 @@ public event EventHandler Exited; public event ErrorHandler Error; - public event MessageHandler Message; public delegate void ErrorHandler( Exception e ); public delegate void MessageHandler( string strMessage ); @@ -342,7 +379,7 @@ THREAD_CREATE, THREAD_END, FUNCTION_DATA, - PROFILER_MESSAGE, + PROFILER_MESSAGE }; const int NETWORK_PROTOCOL_VERSION = 3; @@ -358,5 +395,7 @@ private Project.Options _po; private Run _run; private bool _bHasStopped; + private bool _profilerEnabled; + } } ***** CVS exited normally with code 1 ***** --=====================_51187533==_-- ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://productguide.itmanagersjournal.com/