#include "StdAfx.h" #include "PerfCheck.h" #include #include #include using namespace std; #include "psapi.h" #ifdef _DEBUG #define new new(_NORMAL_BLOCK,__FILE__,__LINE__) #endif int g_nPerfCounter = 0; bool g_bEnableProfile = false; void (__stdcall *s_pProfileOutputDebugFunc)(const char*, ...) = _OutputDebug; void SetProfileOutputDebugFuncPtr( void (__stdcall *Func)(const char*, ...) ) { s_pProfileOutputDebugFunc = Func; } typedef struct tagPERFDATA { double fMinCounter; double fMaxCounter; double fTotalCounter; LARGE_INTEGER prevCounter; DWORD nCountHits; // offset ¿ë double fFpsTotalCounter; DWORD dwFpsCountHits; double fAveFpsTotalCounter; DWORD dwAveFpsCountHits; int nPrevPrefCounter; string strName; } PERFDATA, *LPPERFDATA; static bool PerfCmp(const LPPERFDATA lhs, const LPPERFDATA rhs) { return lhs->fMaxCounter > rhs->fMaxCounter; } class CPerfCheck { public: CPerfCheck() { m_vecPerfDataPtr.reserve(64); } ~CPerfCheck() { OutputPerfInfo(); vector::iterator it = m_vecPerfDataPtr.begin(); vector::iterator itend = m_vecPerfDataPtr.end(); for (; it != itend; it++) delete (*it); } void OutputPerfInfo( void (__stdcall *Func)(const char*, ...) = OutputDebugFunc ) { char buf[256]; vector vecPerfDataPtr; vecPerfDataPtr.assign(m_vecPerfDataPtr.begin(), m_vecPerfDataPtr.end()); vector::iterator it = vecPerfDataPtr.begin(); vector::iterator itend = vecPerfDataPtr.end(); sort(it, itend, PerfCmp); Func("\n\n----- Profiling Result Start -----\n\n"); Func(" [ Func Name ] Call Count MAX(ms) MIN(ms) AVG(ms)\n\n"); LARGE_INTEGER lFreq; QueryPerformanceFrequency(&lFreq); double fFreq = double(lFreq.QuadPart) / 1000.; for (; it != itend; it++) { LPPERFDATA lpPerf = *it; // ±âº»ÀûÀÎ ÇÁ·ÎÆÄÀϸµ °á°ú sprintf(buf, "%-25s %6d, %6.4lf, %6.4lf, %6.4lf \n", lpPerf->strName.c_str(), lpPerf->nCountHits, lpPerf->fMaxCounter / fFreq, (lpPerf->fMinCounter == 100000000. ) ? ( 0. ) : ( lpPerf->fMinCounter / fFreq ), lpPerf->fTotalCounter / fFreq / double(lpPerf->nCountHits) ); Func(buf); // ƽ´ç °è»ê °á°ú if( lpPerf->dwAveFpsCountHits > 0 ) { sprintf(buf, " ¦¦Frame Per Result -> Call : ( %6d ), Ave : ( %6.4lf )\n", lpPerf->dwAveFpsCountHits, lpPerf->fAveFpsTotalCounter / fFreq ); Func(buf); } } Func("\n----- Profiling Result End -----\n\n"); } int RegisterPerfID(const char* lpFnName) { LPPERFDATA pPerfData = new PERFDATA; pPerfData->fMinCounter = 100000000.; pPerfData->fMaxCounter = 0.0; pPerfData->fTotalCounter = 0.0; pPerfData->prevCounter.QuadPart = 0; pPerfData->nCountHits = 0; pPerfData->strName = lpFnName; pPerfData->fFpsTotalCounter = 0.0f; pPerfData->dwFpsCountHits = 0; pPerfData->fAveFpsTotalCounter = 0.f; pPerfData->dwAveFpsCountHits = 0; pPerfData->nPrevPrefCounter = g_nPerfCounter; m_vecPerfDataPtr.push_back(pPerfData); return (int)m_vecPerfDataPtr.size() - 1; } void StartPerfCheck(int nID) { QueryPerformanceCounter(&m_vecPerfDataPtr[nID]->prevCounter); } void EndPerfCheck(int nID) { LARGE_INTEGER currCount; QueryPerformanceCounter(&currCount); LPPERFDATA pPerf = m_vecPerfDataPtr[nID]; double fDiffCount; fDiffCount = double(currCount.QuadPart - pPerf->prevCounter.QuadPart); if (pPerf->fMinCounter > fDiffCount) pPerf->fMinCounter = fDiffCount; else if (pPerf->fMaxCounter < fDiffCount) pPerf->fMaxCounter = fDiffCount; pPerf->fTotalCounter += fDiffCount; pPerf->nCountHits++; if( g_nPerfCounter != pPerf->nPrevPrefCounter ) { bool bFirst = ( pPerf->dwAveFpsCountHits == 0 ) ? true : false; pPerf->fAveFpsTotalCounter += pPerf->fFpsTotalCounter; if( !bFirst ) pPerf->fAveFpsTotalCounter /= 2.f; pPerf->dwAveFpsCountHits += pPerf->dwFpsCountHits; if( !bFirst ) pPerf->dwAveFpsCountHits /= 2; pPerf->fFpsTotalCounter = fDiffCount; pPerf->dwFpsCountHits = 1; pPerf->nPrevPrefCounter = g_nPerfCounter; } else { pPerf->fFpsTotalCounter += fDiffCount; pPerf->dwFpsCountHits++; } } protected: vector m_vecPerfDataPtr; }; // Memory Checker class CProfileMemChecker { public: CProfileMemChecker() {} virtual ~CProfileMemChecker() { OutputResult( NULL ); } protected: struct InfoStruct { std::string szString; unsigned int dwUseMem; int nCallCount; }; struct TempStruct { std::string szString; unsigned int dwCurrentMem; }; std::vector m_vecResult; std::vector m_vecTemp; InfoStruct *FindResult( char *szStr ) { for( DWORD i=0; idwUseMem += dwUseMem; pInfo->nCallCount++; } else { InfoStruct Info; Info.szString = Block.szString; Info.dwUseMem = dwUseMem; Info.nCallCount = 1; m_vecResult.push_back( Info ); } m_vecTemp.erase( m_vecTemp.end() - 1 ); if( bPrintResult ) { OutputResult( (char*)Block.szString.c_str() ); } } void CancleBlock() { m_vecTemp.erase( m_vecTemp.end() - 1 ); } void OutputResult( char *szString = NULL, void (__stdcall *Func)(const char*, ...) = OutputDebugFunc ) { if( szString ) { InfoStruct *pInfo = FindResult( szString ); if( pInfo ) Func( "Mem Checker : [ %s ], Use Mem : %d bytes\n", pInfo->szString.c_str(), pInfo->dwUseMem ); } else { Func( "\n----------------------- Memory Use Result ----------------------------\n" ); Func( "\nFunction Name\tCall Count Total Allocate memory ( byte )\n" ); for( DWORD i=0; iszString.c_str(), pInfo->nCallCount, pInfo->dwUseMem ); } } } }; // Help Func #ifdef ENABLE_PROFILER CPerfCheck s_PerfCheck; CProfileMemChecker s_ProfileMemCheck; int RegisterPerfID(const char* lpFnName) { return s_PerfCheck.RegisterPerfID(lpFnName); } void StartPerfCheck(int nID) { s_PerfCheck.StartPerfCheck(nID); } void EndPerfCheck(int nID) { s_PerfCheck.EndPerfCheck(nID); } void ProfilePrint(void (__stdcall *Func)(const char*, ...)) { s_PerfCheck.OutputPerfInfo(Func); } void StartProfileMemCheck(char *lpFnName) { s_ProfileMemCheck.StartBlock( lpFnName ); } void EndProfileMemCheck() { s_ProfileMemCheck.EndBlock( false ); } void ProfileMemPrint(void (__stdcall *Func)(const char*, ...)) { s_ProfileMemCheck.OutputResult( NULL, Func ); } #else int RegisterPerfID(const char* lpFnName) { return 0; } void StartPerfCheck(int nID) {} void EndPerfCheck(int nID) {} void ProfilePrint(void (__stdcall *Func)(const char*, ...)) {} void StartProfileMemCheck(char *lpFnName) {} void EndProfileMemCheck() {} void ProfileMemPrint(void (__stdcall *Func)(const char*, ...)) {} #endif // ENABLE_PROFILER #ifdef _TEST_CODE_KAL class CProfileMemChecker2 { public: struct InfoStruct { std::string szString; unsigned int dwUseMem; int nCallCount; }; struct TempStruct { std::string szString; unsigned int dwCurrentMem; }; CProfileMemChecker2() {} virtual ~CProfileMemChecker2() { OutputResult(NULL); } void StartBlock(const char *szString) { PROCESS_MEMORY_COUNTERS_EX pmc; memset(&pmc, 0, sizeof(PROCESS_MEMORY_COUNTERS_EX)); pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX); if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(PROCESS_MEMORY_COUNTERS_EX))) { TempStruct Block; Block.szString = szString; Block.dwCurrentMem = pmc.PrivateUsage; m_vecTemp.push_back(Block); } } void EndBlock(bool bPrintResult = true) { if (m_vecTemp.empty()) return; PROCESS_MEMORY_COUNTERS_EX pmc; memset(&pmc, 0, sizeof(PROCESS_MEMORY_COUNTERS_EX)); pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX); if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(PROCESS_MEMORY_COUNTERS_EX))) { TempStruct Block = m_vecTemp[m_vecTemp.size() - 1]; DWORD dwUseMem = (DWORD)(pmc.PrivateUsage - Block.dwCurrentMem); InfoStruct *pInfo = NULL; pInfo = FindResult((char*)Block.szString.c_str()); if (pInfo) { pInfo->dwUseMem += dwUseMem; pInfo->nCallCount++; } else { InfoStruct Info; Info.szString = Block.szString; Info.dwUseMem = dwUseMem; Info.nCallCount = 1; m_vecResult.push_back(Info); } m_vecTemp.erase(m_vecTemp.end() - 1); if (bPrintResult) { OutputResult((char*)Block.szString.c_str()); } } } void CancleBlock() { m_vecTemp.erase(m_vecTemp.end() - 1); } void OutputResult(const char *szString = NULL, void (__stdcall *Func)(const char*, ...) = OutputDebugFunc) { if (szString) { InfoStruct* pInfo = FindResult(szString); if (pInfo) Func("Mem Checker : [ %s ], Use Mem : %d KB\n", pInfo->szString.c_str(), pInfo->dwUseMem / 1024 ); } else { Func( "\n----------------------- Memory Use Result ----------------------------\n" ); Func( "\nFunction Name \t\t Call Count \t\t Total Allocate memory ( byte )\n" ); for( DWORD i=0; iszString.c_str(), pInfo->nCallCount, pInfo->dwUseMem / 1024 ); } } Func( "\n-----------------------------------------------------------------------\n" ); } InfoStruct* FindResult(const char *szStr) { for (DWORD i=0; i m_vecResult; std::vector m_vecTemp; }; CProfileMemChecker2 g_ProfileMemCheck; #endif // _TEST_CODE_KAL