diff options
Diffstat (limited to '')
-rw-r--r-- | public/sdk/inc/perfsnap.hxx | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/public/sdk/inc/perfsnap.hxx b/public/sdk/inc/perfsnap.hxx new file mode 100644 index 000000000..e5404fce6 --- /dev/null +++ b/public/sdk/inc/perfsnap.hxx @@ -0,0 +1,587 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1993. +// +// File: PerfSnap.hxx +// +// Contents: Performace monitor. Snapshots system at user-defined time +// +// Classes: CPerfInfo, CPerformanceMonitor +// +// History: 30-Sep-93 KyleP Created +// +// Notes: These classes only do something interesting if PERFSNAP +// is defined. +// +//-------------------------------------------------------------------------- + +#if !defined(__PERFSNAP_HXX__) +#define __PERFSNAP_HXX__ + +#define USE_NEW_LARGE_INTEGERS + +extern "C" +{ +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#ifdef NEVER +#include <rpc.h> +#include <rpcdce.h> +#endif +} + +#include <stdio.h> +#include <stdlib.h> +#include <windows.h> +#include <debnot.h> +#include <heapstat.h> + +//+------------------------------------------------------------------------- +// +// Class: CPerfInfo +// +// Purpose: Holds snapshot of performance data +// +// History: 30-Sep-93 KyleP Created +// +//-------------------------------------------------------------------------- + +#if defined(PERFSNAP) + +class CPerfInfo +{ +public: + + inline void Init(char const * pszTitle, int const level); + + inline CPerfInfo & operator -(CPerfInfo const & piIn); + + inline void Comment(FILE * pfOut, + char const * pszComment, + LARGE_INTEGER stime); + + inline void Print(FILE * pfOut, LARGE_INTEGER stime); + + inline void _Print(FILE * pfOut); + + inline static void PrintHeader(FILE * pfOut); + +private: + + enum + { + _cbProcPerfXfer = 100 * sizeof(SYSTEM_PROCESS_INFORMATION) + + 500 * sizeof(SYSTEM_THREAD_INFORMATION) + }; + static unsigned char _ProcPerfXfer[_cbProcPerfXfer]; + + int _level; + char _szTitle[100]; + LARGE_INTEGER _time; + SYSTEM_PERFORMANCE_INFORMATION _SysPerf; + SYSTEM_PROCESS_INFORMATION _ProcPerf; + HEAPSTATS _heapStats; + + #ifdef NEVER + // DO NOT SEPARATE + RPC_STATS_VECTOR _rpcStats; + long _rpcExtraSpace[3]; + // END OF DO NOT SEPARATE + #endif +}; + +# define IMPLEMENT_PERFSNAP() \ + unsigned char CPerfInfo::_ProcPerfXfer[CPerfInfo::_cbProcPerfXfer]; + +#else // PERFSNAP + +# define IMPLEMENT_PERFSNAP() + +#endif // PERFSNAP + +//+------------------------------------------------------------------------- +// +// Class: CPerformanceMonitor +// +// Purpose: Monitor performance of system/process at user-defined time. +// +// History: 30-Sep-93 KyleP Created +// +//-------------------------------------------------------------------------- + +class CPerformanceMonitor +{ +public: + + inline CPerformanceMonitor(char const * szFile = 0); + + inline ~CPerformanceMonitor(); + + inline void PrintHeader(); + + inline void Comment(char const * pszComment); + + inline void Snap(char const * pszTitle, int const level); + + inline void Delta(char const * pszTitle, int const level); + +#if defined(PERFSNAP) +private: + + FILE * _pfOut; + int _iLastSnap; + LARGE_INTEGER _time; + CPerfInfo _aSnap[2]; +#endif // PERFSNAP +}; + +inline CPerformanceMonitor::CPerformanceMonitor(char const * szFile) +{ +#if defined(PERFSNAP) + NtQuerySystemTime(&_time); // start time + + _iLastSnap = 0; + if (szFile) + _pfOut = fopen(szFile, "a"); + else + _pfOut = stdout; + fprintf(_pfOut, "\n----------------------------------------\n"); + + _aSnap[0].Init("Start0", 0); + _aSnap[1].Init("Start1", 0); +#endif // PERFSNAP +} + +inline CPerformanceMonitor::~CPerformanceMonitor() +{ +#if defined(PERFSNAP) + fclose(_pfOut); +#endif // PERFSNAP +} + +inline void CPerformanceMonitor::PrintHeader() +{ +#if defined(PERFSNAP) + _aSnap[0].PrintHeader(_pfOut); +#endif // PERFSNAP +} + +inline void CPerformanceMonitor::Comment(char const * pszComment) +{ +#if defined(PERFSNAP) + _aSnap[_iLastSnap].Comment(_pfOut, pszComment, _time); +#endif // PERFSNAP +} + +inline void CPerformanceMonitor::Snap(char const * pszTitle, int const level) +{ +#if defined(PERFSNAP) + _iLastSnap = (_iLastSnap + 1) % 2; + _aSnap[_iLastSnap].Init(pszTitle, level); + _aSnap[_iLastSnap].Print(_pfOut, _time); +#endif // PERFSNAP +} + +inline void CPerformanceMonitor::Delta(char const * pszTitle, int const level) +{ +#if defined(PERFSNAP) + _iLastSnap = (_iLastSnap + 1) % 2; + _aSnap[_iLastSnap].Init(pszTitle, level); + + CPerfInfo piDelta = _aSnap[_iLastSnap] - _aSnap[(_iLastSnap + 1) % 2]; + + // _aSnap[_iLastSnap].Print(_pfOut, _time); + piDelta.Print(_pfOut, _time); +#endif // PERFSNAP +} + +#if defined(PERFSNAP) + +inline void CPerfInfo::Init(char const * pszTitle, int const level) +{ + // + // Get time + // + + NtQuerySystemTime(&_time); + + // + // Set level + // + + _level = level; + + // + // Copy title string + // + + int len = strlen(pszTitle); + if (len > sizeof(_szTitle) - 1) + len = sizeof(_szTitle) - 1; + + memcpy(_szTitle, pszTitle, len); + _szTitle[len] = 0; + + // + // Get performance information + // + + NTSTATUS Status = NtQuerySystemInformation (SystemPerformanceInformation, + &_SysPerf, + sizeof(_SysPerf), + 0); + + Win4Assert(NT_SUCCESS(Status)); + + // + // Process info. Comes back for *all* processes and threads! + // + + Status = NtQuerySystemInformation (SystemProcessInformation, + _ProcPerfXfer, + _cbProcPerfXfer, + 0); + + Win4Assert(NT_SUCCESS(Status)); + + // + // Find the process we care about and copy it out. + // + + HANDLE pid = (HANDLE)NtCurrentTeb()->ClientId.UniqueProcess; + + unsigned char * pb = _ProcPerfXfer; + + while (TRUE) + { + SYSTEM_PROCESS_INFORMATION * pProc = (SYSTEM_PROCESS_INFORMATION *)pb; + + if (pProc->UniqueProcessId == pid) + { + memcpy(&_ProcPerf, pProc, sizeof(SYSTEM_PROCESS_INFORMATION)); + break; + } + + if (pProc->NextEntryOffset == 0) + { + printf("Couldn't find info for process 0x%x\n", pid); + break; + } + + pb += pProc->NextEntryOffset; + } + +#ifdef NEVER + // + // RPC Statistics + // + + RPC_STATS_VECTOR *pStats; + + RpcMgmtInqStats(NULL, &pStats); + memcpy(& _rpcStats, pStats, sizeof(_rpcStats) + sizeof(_rpcExtraSpace)); + RpcMgmtStatsVectorFree(&pStats); +#endif + + // + // (Cairo) Heap Statistics + // + + GetHeapStats(&_heapStats); +} + +inline CPerfInfo & CPerfInfo::operator -(CPerfInfo const & pi2) +{ + CPerfInfo ret; + + // + // Make a delta title + // + + unsigned len = strlen(_szTitle); + memcpy(ret._szTitle, _szTitle, len); + if (len < sizeof(ret._szTitle)-4) + { + memcpy(ret._szTitle + len, " - ", 4); + len += 3; + } + unsigned len2 = strlen(pi2._szTitle); + if (len2 > sizeof(ret._szTitle) - len - 1) + len2 = sizeof(ret._szTitle) - len - 1; + + memcpy(ret._szTitle + len, pi2._szTitle, len2); + ret._szTitle[len+len2] = 0; + + ret._time = _time - pi2._time; + + // + // 'Subtract' performance info + // + + ret._SysPerf.AvailablePages = _SysPerf.AvailablePages - + pi2._SysPerf.AvailablePages; + ret._SysPerf.CommittedPages = _SysPerf.CommittedPages - + pi2._SysPerf.CommittedPages; + ret._SysPerf.PeakCommitment = max(_SysPerf.PeakCommitment, + pi2._SysPerf.PeakCommitment); + ret._SysPerf.PageFaultCount = _SysPerf.PageFaultCount - + pi2._SysPerf.PageFaultCount; + ret._SysPerf.PagedPoolPages = _SysPerf.PagedPoolPages - + pi2._SysPerf.PagedPoolPages; + ret._SysPerf.NonPagedPoolPages = _SysPerf.NonPagedPoolPages - + pi2._SysPerf.NonPagedPoolPages; + + // + // System/LPC calls + // + + ret._SysPerf.SystemCalls = _SysPerf.SystemCalls - pi2._SysPerf.SystemCalls; +#ifdef NEVER + ret._SysPerf.LpcCallOperationCount = _SysPerf.LpcCallOperationCount - + pi2._SysPerf.LpcCallOperationCount; + + // + // RPC + // + + for (int i = 0; i < 4; i++) + ret._rpcStats.Stats[i] = _rpcStats.Stats[i] - pi2._rpcStats.Stats[i]; +#endif + + // + // CPU time + // + + ret._ProcPerf.UserTime = _ProcPerf.UserTime - pi2._ProcPerf.UserTime; + ret._ProcPerf.KernelTime = _ProcPerf.KernelTime - pi2._ProcPerf.KernelTime; + + // + // Memory + // + + ret._ProcPerf.PagefileUsage = _ProcPerf.PagefileUsage - + pi2._ProcPerf.PagefileUsage; + ret._ProcPerf.PeakPagefileUsage = max(_ProcPerf.PeakPagefileUsage, + pi2._ProcPerf.PeakPagefileUsage); + ret._ProcPerf.PrivatePageCount = _ProcPerf.PrivatePageCount - + pi2._ProcPerf.PrivatePageCount; + ret._ProcPerf.QuotaPagedPoolUsage = _ProcPerf.QuotaPagedPoolUsage - + pi2._ProcPerf.QuotaPagedPoolUsage; + ret._ProcPerf.QuotaNonPagedPoolUsage = _ProcPerf.QuotaNonPagedPoolUsage - + pi2._ProcPerf.QuotaNonPagedPoolUsage; + ret._ProcPerf.PeakWorkingSetSize = max(_ProcPerf.PeakWorkingSetSize, + pi2._ProcPerf.PeakWorkingSetSize); + ret._ProcPerf.WorkingSetSize = _ProcPerf.WorkingSetSize - + pi2._ProcPerf.WorkingSetSize; + + // + // Threads + // + + ret._ProcPerf.NumberOfThreads = _ProcPerf.NumberOfThreads - pi2._ProcPerf.NumberOfThreads; + ret._ProcPerf.NumberOfThreads; + + // + // (Cairo) Heap Stats + // + + ret._heapStats.cNew =_heapStats.cNew -pi2._heapStats.cNew; + ret._heapStats.cZeroNew =_heapStats.cZeroNew -pi2._heapStats.cZeroNew; + ret._heapStats.cDelete =_heapStats.cDelete -pi2._heapStats.cDelete; + ret._heapStats.cZeroDelete=_heapStats.cZeroDelete - + pi2._heapStats.cZeroDelete; + ret._heapStats.cRealloc =_heapStats.cRealloc -pi2._heapStats.cRealloc; + ret._heapStats.cbNewed =_heapStats.cbNewed -pi2._heapStats.cbNewed; + ret._heapStats.cbDeleted =_heapStats.cbDeleted-pi2._heapStats.cbDeleted; + + return(ret); +} + +inline void CPerfInfo::PrintHeader(FILE * pfOut) +{ + LARGE_INTEGER time; + SYSTEMTIME systime; + NtQuerySystemTime(&time); + FileTimeToSystemTime((FILETIME *)&time, &systime); + + fprintf(pfOut, + "Performance Run %02d/%02d/%02d %02d:%02d:%02d\n", + systime.wMonth, systime.wDay, systime.wYear, + systime.wHour, systime.wMinute, systime.wSecond); + + fprintf(pfOut, + "Abs/Rel\t" + "Level\t" + "System Time\t" + "System Time ms\t" + "Title\t" + "Physical Memory Available Kb\t" + "Virtual Memory Committed Kb\t" + "Virtual Memory Max Committed Kb\t" + "Virtual Memory Page Faults\t" + "System Total Paged Pool Kb\t" + "System Total Nonpaged Pool Kb\t" + "System Calls\t" + "Process User CPU Time ms\t" + "Process Kernel CPU Time ms\t" + "Process Page File Used pages\t" + "Process Page File Max Used pages\t" + "Process Page File Private pages\t" + "Process Paged Pool pages\t" + "Process Nonpaged Pool pages\t" + "Process #Threads\t" + "Working Set Peak Kb\t" + "Working Set Current Kb\t" + "Heap Allocs\t" + "0-len Heap Allocs\t" + "Heap Deletes\t" + "0-len Heap Deletes\t" + "Heap Reallocs\t" + "Heap Allocated bytes\t" + "Heap Freed bytes\t" + "Process ID\t" + "Thread ID\t" + "Time To Snap ms\t" + "System Time ms absolute\n"); +} + + +inline void CPerfInfo::_Print(FILE * pfOut) +{ + // LPCCallOperationsCount not printed: its bogus + // _rpcStats[0..3] not printed: never non-zero + // "RPC Calls In\tRPC Calls Out\tRPC Packets In\tRPC Packets Out\t" + + fprintf(pfOut, + "%ld\t" + "%ld\t" + "%ld\t" + "%lu\t" + "%ld\t" + "%ld\t" + "%lu\t" + "%lu\t" + "%lu\t" + "%ld\t" + "%ld\t" + "%ld\t" + "%ld\t" + "%ld\t" + "%ld\t" + "%ld\t" + "%ld\t" + "%lu\t" + "%lu\t" + "%lu\t" + "%lu\t" + "%lu\t" + "%lu\t" + "%lu\t" + "%ld\t" + "%ld", + _SysPerf.AvailablePages * 4, + _SysPerf.CommittedPages * 4, + _SysPerf.PeakCommitment * 4, + _SysPerf.PageFaultCount, + _SysPerf.PagedPoolPages * 4, + _SysPerf.NonPagedPoolPages * 4, + _SysPerf.SystemCalls, + (_ProcPerf.UserTime.LowPart+5000) / 10000, + (_ProcPerf.KernelTime.LowPart+5000) / 10000, + (_ProcPerf.PagefileUsage+1023) / 1024, + (_ProcPerf.PeakPagefileUsage+1023) / 1024, + (_ProcPerf.PrivatePageCount+1023) / 1024, + (_ProcPerf.QuotaPagedPoolUsage+1023) / 1024, + (_ProcPerf.QuotaNonPagedPoolUsage+1023) / 1024, + _ProcPerf.NumberOfThreads, + (_ProcPerf.PeakWorkingSetSize+1023) / 1024, + (_ProcPerf.WorkingSetSize+1023) / 1024, + _heapStats.cNew, + _heapStats.cZeroNew, + _heapStats.cDelete, + _heapStats.cZeroDelete, + _heapStats.cRealloc, + _heapStats.cbNewed, + _heapStats.cbDeleted, + GetCurrentProcessId(), + GetCurrentThreadId() + ); + +} + +#define CVT_TO_MS(t) (((t.wHour*60 + t.wMinute)*60 + t.wSecond)*1000 + t.wMilliseconds) + +inline void CPerfInfo::Print(FILE * pfOut, LARGE_INTEGER stime) +{ + LARGE_INTEGER time; + LARGE_INTEGER dtime; + SYSTEMTIME systime; + + _szTitle[sizeof(_szTitle)-1] = '\0'; + + // + // Time is either a delta or absolute. + // + + if (_time.HighPart > 0) + { + SYSTEMTIME systime; + FileTimeToSystemTime((FILETIME *)&_time, &systime); + dtime = _time - stime; + fprintf(pfOut, + "A\t%d\t%02d:%02d:%02d.%03d\t%u\t%s\t", + _level, + systime.wHour, systime.wMinute, systime.wSecond, + systime.wMilliseconds, + dtime.LowPart / 10000, + _szTitle); + } + else + { + // FILETIME is in units of 100 nanoseconds (== 0.1 ms) + fprintf(pfOut, + "R\t%d\t\t%u\t%s\t", + _level, + _time.LowPart / 10000, + _szTitle); + } + + _Print(pfOut); + + // A FILETIME is in units of 100 nanoseconds (== 0.1 ms) + NtQuerySystemTime(&time); + dtime = time - _time; + FileTimeToSystemTime((FILETIME*)&_time, &systime); + fprintf(pfOut, "\t%d\t%d\n", dtime.LowPart / 10000, CVT_TO_MS(systime)); +} + + +inline void CPerfInfo::Comment(FILE * pfOut, char const * pszComment, + LARGE_INTEGER stime) +{ + SYSTEMTIME systod; + LARGE_INTEGER time; + LARGE_INTEGER tod; + LARGE_INTEGER dtime; + + NtQuerySystemTime(&tod); + FileTimeToSystemTime((FILETIME*)&tod, &systod); + dtime = tod - stime; + + fprintf(pfOut, "C\t0\t%02d:%02d:%02d.%03d\t%d\t%s\t", + systod.wHour, systod.wMinute, systod.wSecond, + systod.wMilliseconds, + dtime.LowPart / 10000, + pszComment); + + _Print(pfOut); + + NtQuerySystemTime(&time); + dtime = time - tod; + fprintf(pfOut, "\t%d\t%d\n", dtime.LowPart / 10000, CVT_TO_MS(systod)); +} + +#endif // PERFSNAP +#endif // __PERFSNAP_HXX__ |