base init
This commit is contained in:
274
src/game/profiler.h
Normal file
274
src/game/profiler.h
Normal file
@@ -0,0 +1,274 @@
|
||||
#ifndef __INC_METIN_II_GAME_PROFILER_H__
|
||||
#define __INC_METIN_II_GAME_PROFILER_H__
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class CProfiler : public singleton<CProfiler>
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
STACK_DATA_MAX_NUM = 64,
|
||||
};
|
||||
|
||||
public:
|
||||
typedef struct SProfileStackData
|
||||
{
|
||||
int iCallStep;
|
||||
long iStartTime;
|
||||
long iEndTime;
|
||||
|
||||
std::string strName;
|
||||
} TProfileStackData;
|
||||
|
||||
typedef struct SProfileAccumData
|
||||
{
|
||||
int iStartTime;
|
||||
int iCallingCount;
|
||||
int iCollapsedTime;
|
||||
int iDepth;
|
||||
|
||||
std::string strName;
|
||||
} TProfileAccumData;
|
||||
|
||||
struct stringhash
|
||||
{
|
||||
size_t operator () (const std::string& str) const
|
||||
{
|
||||
const unsigned char * s = (const unsigned char *) str.c_str();
|
||||
const unsigned char * end = s + str.size();
|
||||
size_t h = 0;
|
||||
|
||||
while (s < end)
|
||||
{
|
||||
h *= 16777619;
|
||||
h ^= (unsigned char) *(unsigned char *) (s++);
|
||||
}
|
||||
|
||||
return h;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unordered_map<std::string, TProfileAccumData> TProfileAccumDataMap;
|
||||
|
||||
public:
|
||||
CProfiler()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
virtual ~CProfiler()
|
||||
{
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
m_iAccumDepth = 0;
|
||||
m_ProfileStackDataCount = 0;
|
||||
m_iCallStep = 0;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
TProfileAccumDataMap::iterator it = m_ProfileAccumDataMap.begin();
|
||||
|
||||
for (; it != m_ProfileAccumDataMap.end(); ++it)
|
||||
{
|
||||
TProfileAccumData & rData = it->second;
|
||||
rData.iCallingCount = 0;
|
||||
rData.iCollapsedTime = 0;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Push(const char * c_szName)
|
||||
{
|
||||
assert(m_ProfileStackDataCount < STACK_DATA_MAX_NUM);
|
||||
TProfileStackData & rProfileStackData = m_ProfileStackDatas[m_ProfileStackDataCount++];
|
||||
|
||||
rProfileStackData.iCallStep = m_iCallStep;
|
||||
rProfileStackData.iStartTime = get_dword_time();
|
||||
rProfileStackData.strName = c_szName;
|
||||
|
||||
++m_iCallStep;
|
||||
}
|
||||
|
||||
void Pop(const char * c_szName)
|
||||
{
|
||||
TProfileStackData * pProfileStackData;
|
||||
|
||||
if (!GetProfileStackDataPointer(c_szName, &pProfileStackData))
|
||||
{
|
||||
assert(!"The name doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
pProfileStackData->iEndTime = get_dword_time();
|
||||
--m_iCallStep;
|
||||
}
|
||||
|
||||
__inline void PushAccum(const char * c_szName)
|
||||
{
|
||||
TProfileAccumDataMap::iterator it = m_ProfileAccumDataMap.find(c_szName);
|
||||
|
||||
if (it == m_ProfileAccumDataMap.end())
|
||||
{
|
||||
TProfileAccumData ProfileAccumData;
|
||||
|
||||
ProfileAccumData.iCollapsedTime = 0;
|
||||
ProfileAccumData.iCallingCount = 0;
|
||||
ProfileAccumData.strName = c_szName;
|
||||
ProfileAccumData.iDepth = m_iAccumDepth;
|
||||
|
||||
m_ProfileAccumDataMap.insert(TProfileAccumDataMap::value_type(c_szName, ProfileAccumData));
|
||||
it = m_ProfileAccumDataMap.find(c_szName);
|
||||
m_vec_Accum.push_back(&it->second);
|
||||
}
|
||||
|
||||
TProfileAccumData & rData = it->second;
|
||||
rData.iStartTime = get_dword_time();
|
||||
++m_iAccumDepth;
|
||||
}
|
||||
|
||||
__inline void PopAccum(const char * c_szName)
|
||||
{
|
||||
TProfileAccumDataMap::iterator it = m_ProfileAccumDataMap.find(c_szName);
|
||||
|
||||
if (it == m_ProfileAccumDataMap.end())
|
||||
return;
|
||||
|
||||
TProfileAccumData & rData = it->second;
|
||||
rData.iCollapsedTime += get_dword_time() - rData.iStartTime;
|
||||
++rData.iCallingCount;
|
||||
--m_iAccumDepth;
|
||||
}
|
||||
|
||||
void Log(const char * c_pszFileName)
|
||||
{
|
||||
FILE * fp = fopen(c_pszFileName, "w");
|
||||
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
Print(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void Print(FILE * fp = stderr)
|
||||
{
|
||||
for (int i = 0; i < m_ProfileStackDataCount; ++i)
|
||||
{
|
||||
TProfileStackData & rProfileStackData = m_ProfileStackDatas[i];
|
||||
|
||||
for (int i = 0; i < rProfileStackData.iCallStep; ++i)
|
||||
fprintf(fp, "\t");
|
||||
|
||||
fprintf(fp, "%-24s: %lu\n", rProfileStackData.strName.c_str(), rProfileStackData.iEndTime - rProfileStackData.iStartTime);
|
||||
}
|
||||
|
||||
fprintf(fp, "Name Call/Load Ratio\n");
|
||||
|
||||
std::string stLine;
|
||||
|
||||
for (DWORD k = 0; k < m_vec_Accum.size(); ++k)
|
||||
{
|
||||
TProfileAccumData * p = m_vec_Accum[k];
|
||||
|
||||
stLine.assign(p->iDepth * 5, ' ');
|
||||
stLine += p->strName;
|
||||
|
||||
fprintf(fp, "%-30s %10d/%-10d %.2f\n",
|
||||
stLine.c_str(),
|
||||
p->iCallingCount, p->iCollapsedTime,
|
||||
p->iCallingCount != 0 ? (float) p->iCollapsedTime / p->iCallingCount : 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintOneStackData(const char * c_szName)
|
||||
{
|
||||
TProfileStackData * pProfileStackData;
|
||||
|
||||
if (!GetProfileStackDataPointer(c_szName, &pProfileStackData))
|
||||
return;
|
||||
|
||||
sys_log(0, "%-10s: %3d", pProfileStackData->strName.c_str(), pProfileStackData->iEndTime - pProfileStackData->iStartTime);
|
||||
}
|
||||
|
||||
void PrintOneAccumData(const char * c_szName)
|
||||
{
|
||||
TProfileAccumDataMap::iterator it = m_ProfileAccumDataMap.find(c_szName);
|
||||
|
||||
if (it == m_ProfileAccumDataMap.end())
|
||||
return;
|
||||
|
||||
TProfileAccumData & rData = it->second;
|
||||
|
||||
sys_log(0, "%-10s : [CollapsedTime : %3d] / [CallingCount : %3d]",
|
||||
rData.strName.c_str(),
|
||||
rData.iCollapsedTime,
|
||||
rData.iCallingCount);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool GetProfileStackDataPointer(const char * c_szName, TProfileStackData ** ppProfileStackData)
|
||||
{
|
||||
for (int i = 0; i < m_ProfileStackDataCount; ++i)
|
||||
{
|
||||
if (0 == m_ProfileStackDatas[i].strName.compare(c_szName))
|
||||
{
|
||||
*ppProfileStackData = &m_ProfileStackDatas[i];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Profile Stack Data
|
||||
int m_ProfileStackDataCount;
|
||||
TProfileStackData m_ProfileStackDatas[STACK_DATA_MAX_NUM];
|
||||
|
||||
// Profile Accum Data
|
||||
TProfileAccumDataMap m_ProfileAccumDataMap;
|
||||
std::vector<TProfileAccumData *> m_vec_Accum;
|
||||
int m_iAccumDepth;
|
||||
|
||||
int m_iCallStep;
|
||||
};
|
||||
|
||||
template <typename T> class CProfileUnit
|
||||
{
|
||||
public:
|
||||
CProfileUnit(const char * c_pszName)
|
||||
{
|
||||
m_stName = c_pszName;
|
||||
CProfiler::instance().PushAccum(m_stName.c_str());
|
||||
m_bPushed = true;
|
||||
}
|
||||
|
||||
~CProfileUnit()
|
||||
{
|
||||
if (m_bPushed)
|
||||
Pop();
|
||||
}
|
||||
|
||||
void Pop()
|
||||
{
|
||||
if (m_bPushed)
|
||||
{
|
||||
CProfiler::instance().PopAccum(m_stName.c_str());
|
||||
m_bPushed = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_stName;
|
||||
bool m_bPushed;
|
||||
};
|
||||
|
||||
#define PROF_UNIT CProfileUnit<void>
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user