Files
mir_server/Gateway/common/statistic/time_stat.h

296 lines
7.9 KiB
C
Raw Normal View History

2025-01-09 17:45:40 +08:00
#ifndef _TIME_STAT_H_
#define _TIME_STAT_H_
#ifdef _MSC_VER
//////////////////////////////////////////////////////////////////////////
// ʱ<><CAB1>ͳ<EFBFBD>Ʒ<EFBFBD><C6B7><EFBFBD><EFBFBD><EFBFBD>
// <20><> <09>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD>׷<EFBFBD>ٳ<EFBFBD><D9B3><EFBFBD><EFBFBD>е<EFBFBD><D0B5>õĺ<C3B5><C4BA><EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƿ<EFBFBD><C6BF>
// ˵ <09><><EFBFBD><EFBFBD>ͳ<EFBFBD>ư<EFBFBD><C6B0><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD><D0BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <09>ڵ<EFBFBD><DAB5><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD><CEBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF>ٵķ<D9B5><C4B7><EFBFBD><EFBFBD><EFBFBD>
// 2<><32><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>ÿ<EFBFBD><C3BF>ִ<EFBFBD>е<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><CBB6><EFBFBD>ʱ<EFBFBD><EFBFBD>ҳ<EFBFBD>ƿ<EFBFBD><C6BF><EFBFBD><EFBFBD><EFBFBD>ڡ<EFBFBD>
// <20><><EFBFBD><EFBFBD><E7A3BA><EFBFBD>߼<EFBFBD><DFBC>̣߳<DFB3><CCA3><EFBFBD><EFBFBD>߼<EFBFBD><DFBC>߳<EFBFBD>ÿ<EFBFBD><C3BF>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>׷<EFBFBD>ٽڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E7B4A6><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵȶ<C8B5><C8B6><EFBFBD><EFBFBD><EFBFBD>׷<EFBFBD>ٽڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>ĸ<EFBFBD><C4B8>ٵ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>ʱռ<CAB1><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <09><>Ϊ<EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD><E6B1BE><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><EFBFBD><E4A3AC><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD>
// ͳ<>Ʒ<EFBFBD><C6B7><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><EFBFBD><ECA3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2>ռ<EFBFBD><D5BC>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>50%<25><><EFBFBD>ҵ<EFBFBD>ʱ<EFBFBD><EFBFBD><E4A3AC><EFBFBD><EFBFBD>
// <20><>Ϊ<EFBFBD><CEAA>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>ˢ<EFBFBD>³<EFBFBD><C2B3><EFBFBD><EFBFBD>⣬Ҳ<E2A3AC><D2B2><EFBFBD><EFBFBD><E2B2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <09><><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>⣬Ҫô<D2AA><C3B4><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>˷<EFBFBD>ʱ<EFBFBD><CAB1>Ҫô<D2AA><C3B4><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD>÷<EFBFBD>ʱ׷<CAB1>ٽ<EFBFBD><D9BD>
//////////////////////////////////////////////////////////////////////////
#include <new>
//#include "ObjectCounter.h"
class TimeProfDummy
{
public:
TimeProfDummy(const char* szUnitName, unsigned int nHashCode);
~TimeProfDummy();
};
// ִ<><D6B4>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>¼<EFBFBD>ڵ<EFBFBD>
class TimeProfRecord
{
public:
enum
{
MAX_EXEC_UNIT_NAME_LEN = 64, // <20><><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
};
TimeProfRecord(){}
TimeProfRecord(const char* szUnitName, unsigned int nHashCode);
~TimeProfRecord();
//<2F><><EFBFBD>ýڵ<C3BD><DAB5><EFBFBD><EFBFBD><EFBFBD>
void setName(const char* szName);
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>
inline void addChild(TimeProfRecord* record)
{
m_childrenNode.add(record);
}
// <20><>ѯ<EFBFBD>ڵ<EFBFBD>
//CTimeProfRecord* getChild(const char* szUnitName);
inline TimeProfRecord* getChildByHash(int nHashCode)
{
for (int i = 0; i < m_childrenNode.count(); i++)
{
if ((unsigned int)nHashCode == m_childrenNode[i]->m_nNameHashCode)
return m_childrenNode[i];
}
return NULL;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ
void dump(stream::BaseStream& stream, int level = 0);
// <20><><EFBFBD>ýڵ<C3BD><DAB5><EFBFBD><EFBFBD><EFBFBD>
inline void reset(bool bIncOccuData = false)
{
m_nTotalCount = 0;
m_nMaxTime = 0;
m_nMinTime = 0;
m_nTotalTime = 0;
if (bIncOccuData)
{
m_nOccuTotalCount = 0;
m_nOccuTotalTime = 0;
m_nOccuMaxTime = 0;
m_nOccuMinTime = 0;
}
}
inline void reInitBasicData(const char* szUnitName, unsigned int nHashCode)
{
ZeroMemory(this, offsetof(TimeProfRecord, m_childrenNode));
_STRNCPY_A(m_szExecUnitName, szUnitName);
for (int i = 0; i < (int)strlen(m_szExecUnitName); i++)
{
if (m_szExecUnitName[i] == ('\"') || m_szExecUnitName[i] == (',') || m_szExecUnitName[i] == ('<')
|| m_szExecUnitName[i] == ('>') || m_szExecUnitName[i] == (':') || m_szExecUnitName[i] == (' '))
m_szExecUnitName[i] = ('_');
}
m_nNameHashCode = nHashCode;
}
inline void startProf()
{
m_nStartTime = _getTickCount();
m_nTotalCount++;
m_nOccuTotalCount++;
}
inline void endProf()
{
m_nEndTime = _getTickCount();
unsigned long long nTimeConsume = m_nEndTime - m_nStartTime;
if (m_nMaxTime < nTimeConsume)
m_nMaxTime = nTimeConsume;
if (m_nMinTime > nTimeConsume)
m_nMinTime = nTimeConsume;
if (m_nOccuMaxTime < nTimeConsume)
m_nOccuMaxTime = nTimeConsume;
if (m_nOccuMinTime > nTimeConsume)
m_nOccuMinTime = nTimeConsume;
m_nTotalTime += nTimeConsume;
m_nOccuTotalTime += nTimeConsume;
}
void clear();
//<2F>ַ<EFBFBD><D6B7><EFBFBD>hash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><E1B9A9><EFBFBD><EFBFBD>
inline static unsigned int hashlstr(const char* str, size_t len)
{
unsigned int h = (unsigned int)len;
size_t step = (len>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=len; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+(unsigned char)str[l1-1]);
return h;
}
protected:
unsigned int m_nNameHashCode; // <20><><EFBFBD><EFBFBD>Hash<73><68>
unsigned long long m_nTotalCount; // ִ<>д<EFBFBD><D0B4><EFBFBD>
unsigned long long m_nOccuTotalCount; // <20>ۻ<EFBFBD>ִ<EFBFBD>д<EFBFBD><D0B4><EFBFBD>
unsigned long long m_nMaxTime; // <20><><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>к<EFBFBD>ʱ
unsigned long long m_nMinTime; // <20><><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD>Сִ<D0A1>к<EFBFBD>ʱ
unsigned long long m_nOccuMaxTime; // <20>ۻ<EFBFBD><DBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>к<EFBFBD>ʱ
unsigned long long m_nOccuMinTime; // <20>ۻ<EFBFBD><DBBB><EFBFBD><EFBFBD><EFBFBD>Сִ<D0A1>к<EFBFBD>ʱ
unsigned long long m_nTotalTime; // <20><><EFBFBD><EFBFBD>ִ<EFBFBD>к<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
unsigned long long m_nOccuTotalTime; // <20>ۻ<EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1>
unsigned long long m_nStartTime; // <20><>ʼִ<CABC><D6B4>ʱ<EFBFBD><CAB1>
unsigned long long m_nEndTime; // <20><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1>
char m_szExecUnitName[MAX_EXEC_UNIT_NAME_LEN]; // ִ<>е<EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>
container::Vector<TimeProfRecord*> m_childrenNode; // <20><><EFBFBD><EFBFBD><EFBFBD>ӽڵ<D3BD><DAB5>б<EFBFBD>
};
// ִ<><D6B4>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
class TimeProfMgr
{
public:
TimeProfMgr();
~TimeProfMgr();
enum
{
ALLOC_RECORD_NUM = 200,
};
bool InitMgr()
{
if (TLS_OUT_OF_INDEXES == s_dwTlsIdx)
{
s_dwTlsIdx = TlsAlloc();
return s_dwTlsIdx != TLS_OUT_OF_INDEXES ? true : false;
}
return false;
}
static TimeProfMgr& getSingleton()
{
static TimeProfMgr mgr;
return mgr;
}
TimeProfMgr* getThreadInst()
{
TimeProfMgr* profMgr = (TimeProfMgr *)TlsGetValue(s_dwTlsIdx);
if (!profMgr)
{
profMgr = new TimeProfMgr();
profMgr->setThreadId(GetCurrentThreadId());
TlsSetValue(s_dwTlsIdx, profMgr);
m_lock.Lock();
m_vecTimeProfMgr.add(profMgr);
m_lock.Unlock();
}
return profMgr;
}
// <20><>ʼִ<CABC>м<EFBFBD>ʱ
inline void OnTimeProfRecordStart(TimeProfRecord *record)
{
m_execUnitStack.push(record);
}
// <20><><EFBFBD><EFBFBD>ִ<EFBFBD>м<EFBFBD>ʱ
inline void OnTimeProfRecordEnd(TimeProfRecord *)
{
m_execUnitStack.pop();
}
// <20><>ȡ<EFBFBD><C8A1>ǰִ<C7B0>е<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
inline TimeProfRecord* getCurrTimeProfRecord()
{
int count = m_execUnitStack.count();
if (count > 0)
return m_execUnitStack[count-1];
return NULL;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8>Ϣ
void dump();
inline TimeProfRecord* allocRecord()
{
if (m_freeRecordList.count() <= 0)
allocTimeProfRecord();
return m_freeRecordList.pop();
}
inline void freeRecord(TimeProfRecord *record)
{
m_freeRecordList.add(record);
}
inline void clear()
{
m_execUnitRoot.clear();
for (int i = 0; i < m_freeRecordList.count(); i++)
{
TimeProfRecord *pRecord = m_freeRecordList[i];
if (pRecord)
{
pRecord->~TimeProfRecord();
free(pRecord);
}
}
m_freeRecordList.empty();
m_execUnitStack.empty();
if (s_dwTlsIdx != TLS_OUT_OF_INDEXES)
{
TlsFree(s_dwTlsIdx);
s_dwTlsIdx = TLS_OUT_OF_INDEXES;
}
for (int i = 0; i < m_vecTimeProfMgr.count(); i++)
{
delete m_vecTimeProfMgr[i];
}
m_vecTimeProfMgr.empty();
}
protected:
// <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ͷ
void dumpDateTimeHeader(stream::BaseStream& stream);
// <20><><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>
void dumpDateTimeSep(stream::BaseStream& stream);
// <20><>ȡ<EFBFBD><C8A1>ǰʱ<C7B0><CAB1>
void getCurrentTm(tm &t);
// dump
void dumpImpl(stream::BaseStream& stream);
// <20><>ʽ<EFBFBD><CABD>ʱ<EFBFBD><CAB1>
void formatTimeStr(char* szDataBuff, size_t nLen, tm *t);
// ִ<><D6B4>һ<EFBFBD>η<EFBFBD><CEB7>䣨ÿ<E4A3A8>η<EFBFBD><CEB7><EFBFBD>ALLOC_RECORD_NUM<55><4D><EFBFBD><EFBFBD>
inline void allocTimeProfRecord()
{
for (int i = 0; i < ALLOC_RECORD_NUM; i++)
{
TimeProfRecord* pRecords = (TimeProfRecord *)malloc(sizeof(TimeProfRecord));
if (pRecords)
{
new (pRecords)TimeProfRecord();
m_freeRecordList.add(pRecords);
}
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>Id
inline void setThreadId(DWORD dwThreadId) { m_dwThreadId = dwThreadId; }
protected:
container::Vector<TimeProfRecord *> m_execUnitStack; // ִ<>е<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ջ
TimeProfRecord m_execUnitRoot; // ִ<>е<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD>ĸ<EFBFBD><C4B8>ڵ<EFBFBD>
tm m_lastDumpTime; // <20>ϴ<EFBFBD>dump<6D><70><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
container::Vector<TimeProfRecord*> m_freeRecordList;
static DWORD s_dwTlsIdx; // Tls Slot Index
lock::Mutex m_lock; // Sync for multithread create timeprofmgr object
container::Vector<TimeProfMgr*> m_vecTimeProfMgr; // TimeProfMgr list
DWORD m_dwThreadId; // Current ThreadId
};
#ifdef _TIME_STATE_CHECK_
#define DECLARE_TIME_PROF(name) static unsigned int _STATIC_FUNCTION_HASH_VALUE_= TimeProfRecord::hashlstr(name,strlen(name)); \
TimeProfDummy LocalTimeProfRecord(name, _STATIC_FUNCTION_HASH_VALUE_ );
#define DECLARE_FUN_TIME_PROF() DECLARE_TIME_PROF(__FUNCTION__)
#else
#define DECLARE_TIME_PROF(name_)
#define DECLARE_FUN_TIME_PROF() DECLARE_TIME_PROF(__FUNCTION__)
#endif
#endif
#endif