Files
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

196 lines
5.3 KiB
C++

#ifndef _FUNCTION_PERFORMANCE_CHECK_H_
#define _FUNCTION_PERFORMANCE_CHECK_H_
#include <winsock2.h>
#include <windows.h>
#include <map>
#include "../../Thread/Lock.h"
#include "../../Pattern/Singleton.h"
#define _USING_REALCLOCK
#if defined(_USING_REALCLOCK) && _M_IX86 >= 500
#define RealClock(Large_Integer_In) \
{ __asm rdtsc __asm mov Large_Integer_In.HighPart, edx __asm mov Large_Integer_In.LowPart, eax }
#define ClockSnapShot(Large_Integer_Out, UniqueVariableName) \
LARGE_INTEGER SnapShot##UniqueVariableName; \
RealClock(SnapShot##UniqueVariableName); \
Large_Integer_Out = SnapShot##UniqueVariableName
#define ClockPerSec(Large_Integer_Frequency_Out, UniqueVariableName) \
LARGE_INTEGER Start##UniqueVariableName, Stop##UniqueVariableName; \
RealClock(Start##UniqueVariableName) \
Sleep(1000); \
RealClock(Stop##UniqueVariableName) \
Large_Integer_Frequency_Out.QuadPart = \
Stop##UniqueVariableName.QuadPart - Start##UniqueVariableName.QuadPart - 57UL
#else
#define ClockSnapShot(Large_Integer_Out, UniqueVariableName) \
QueryPerformanceCounter(&Large_Integer_Out)
#define ClockPerSec(Large_Integer_Frequency_Out, UniqueVariableName) \
QueryPerformanceFrequency(&Large_Integer_Frequency_Out)
#endif
// ------------------------------------------------------------------------------------------------
// 한 함수에서 여러 개 만들 수 있음.
// identifiler는 변수명에 포함되므로, 변수명의 명명 규칙과 동일하게 할 것.
// blockName은 반드시 문자열 리터럴로 할 것.
#define DeclareBlockTimingCheck(blockName, identifiler) \
CPerformanceInstrument blockInstrument##identifiler(blockName);
#define BlockTimingCheckStart(identifiler) \
blockInstrument##identifiler.Start();
#define BlockTimingCheckStop(identifiler) \
blockInstrument##identifiler.Stop();
// ------------------------------------------------------------------------------------------------
// 한 함수에서 한개만 쓸 수 있음.
#define FunctionTimingCheck \
CPerformanceInstrument functionInstrument(__FUNCTION__); \
CAutoInstrument autofunctionInstrument(functionInstrument);
// 결과를 파일로 출력. 출력한 후, 정보를 전부 초기화한다.
#define GetFunctionTimingResult(fileName) \
CPerformanceCheck::GetInstance().PrintAllTime(fileName);
// 결과를 파일로 출력. 출력한 후, 정보를 초기화하지 않는다.
#define GetFunctionTimingResultNoReset(fileName) \
CPerformanceCheck::GetInstance().PrintAllTime(fileName, false);
class CPerformanceCheck
{
public:
static CPerformanceCheck& GetInstance();
typedef void (*FnPrintUserMessage) (FILE* fDescriptor);
void SetUserMessageFunc(FnPrintUserMessage fnPreFix = 0, FnPrintUserMessage fnPostFix = 0);
void AddTime(const char* szfunctionName, double fEstimateTime);
bool PrintAllTime(const char* fileName, bool bReset = true);
private:
CPerformanceCheck();
~CPerformanceCheck();
// 전방 참조
struct Instrument
{
double m_fProcessTime;
double m_fMinTime;
double m_fMaxTime;
unsigned long m_dwHashKey;
unsigned long m_dwCalled;
const char* m_szFunctionName;
Instrument(unsigned long dwHashKey, double fProcessTime, const char* szFunctionName)
: m_dwHashKey(dwHashKey), m_fProcessTime(fProcessTime), m_dwCalled(1),
m_fMinTime(fProcessTime), m_fMaxTime(fProcessTime),
m_szFunctionName(szFunctionName) { }
Instrument()
: m_fProcessTime(0.0f), m_fMinTime(0.0f), m_fMaxTime(0.0f),
m_dwCalled(1), m_dwHashKey(0),
m_szFunctionName(NULL) { }
void Initialize()
{
m_fProcessTime = m_fMinTime = m_fMaxTime = 0.0f;
m_dwCalled = 0;
}
};
typedef CCSLock PerformanceCheckLock;
typedef std::multimap<unsigned long, Instrument> PerformanceTable;
PerformanceCheckLock m_TableLock;
CACHE_PAD(PerformanceCheckLockPad, sizeof(PerformanceCheckLock));
LARGE_INTEGER m_Frequency;
double m_fFrequency;
PerformanceTable m_InstrumentTable;
FnPrintUserMessage m_fnPreFix;
FnPrintUserMessage m_fnPostFix;
};
class CPerformanceInstrument
{
public:
CPerformanceInstrument(char* szfunctionName)
: m_szfunctionName(szfunctionName)
{
m_startTime.QuadPart = 0;
CPerformanceCheck::GetInstance().AddTime(m_szfunctionName, 0);
}
CPerformanceInstrument()
: m_szfunctionName(0)
{
m_startTime.QuadPart = 0;
}
void SetName(char* szfunctionName) { m_szfunctionName = szfunctionName; }
~CPerformanceInstrument() { }
inline void Start();
inline void Stop();
private:
LARGE_INTEGER m_startTime;
LARGE_INTEGER m_stopTime;
char* m_szfunctionName;
};
inline void CPerformanceInstrument::Start()
{
m_stopTime.QuadPart = 0;
ClockSnapShot(m_startTime, startTime);
}
inline void CPerformanceInstrument::Stop()
{
ClockSnapShot(m_stopTime, stopTime);
if(0 == m_stopTime.QuadPart) { ++m_stopTime.QuadPart; }
CPerformanceCheck::GetInstance().AddTime(m_szfunctionName,
static_cast<double>(m_stopTime.QuadPart - m_startTime.QuadPart));
}
class CAutoInstrument
{
public:
CAutoInstrument(CPerformanceInstrument& PerformanceInstrument)
: m_PerformanceInstrument(PerformanceInstrument) { m_PerformanceInstrument.Start(); }
~CAutoInstrument() { m_PerformanceInstrument.Stop(); }
private:
CPerformanceInstrument& m_PerformanceInstrument;
};
#endif