123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- #include "PerfTimer.h"
- #include "BFApp.h"
- #pragma warning(disable:4996)
- #ifdef _DEBUG
- #define PERF_WANTS_THREAD_CHECK
- #endif
- USING_NS_BF;
- PerfManager* Beefy::gPerfManager = NULL;
- PerfEntry::PerfEntry()
- {
- mCount = 0;
- mTimeTotal = 0;
- mCurTimingStart = 0;
- mChild = NULL;
- }
- void PerfEntry::DbgPrint(const StringImpl& name, int level, std::map<String, int>& uniqueTimingMap)
- {
- String text;
- uint64 childrenTime = 0;
-
- /*PerfEntryMap::iterator itr = mChildren.begin();
- while (itr != mChildren.end())
- {
- PerfEntry* child = &itr->second;
- childrenTime += child->mTimeTotal;
- ++itr;
- }*/
- for (auto& kv : mChildren)
- {
- PerfEntry* child = kv.mValue;
- childrenTime += child->mTimeTotal;
- }
- for (int i = 0; i <= level; i++)
- text += " ";
- String prefix = text;
- text += name;
-
- while (text.length() < 80)
- text += ' ';
-
- int selfTime = (int)(mTimeTotal - childrenTime);
- if (uniqueTimingMap.find(name) == uniqueTimingMap.end())
- uniqueTimingMap[name] = selfTime;
- else
- uniqueTimingMap[name] += selfTime;
- text += StrFormat("%4d\t%6.1f\t%6.1f\n", mCount, mTimeTotal / 1000.0f, (int) (selfTime) / 1000.0f);
- /*for (int i = 0; i < (int) mLog.size(); i++)
- {
- PerfLogEntry* logEntry = &mLog[i];
- text += prefix + StrFormat("@%d: %s\n", logEntry->mTick, logEntry->mString.c_str());
- }*/
-
- OutputDebugStrF(text.c_str());
- for (auto& kv : mChildren)
- {
- PerfEntry* child = kv.mValue;
- child->DbgPrint(kv.mKey, level + 1, uniqueTimingMap);
- }
- }
- void PerfManager::Clear()
- {
- mLogEntries.ClearFast();
- mAlloc.Clear();
- mFrames.clear();
- mCurStackIdx = 0;
- mOverhead = 0;
- }
- PerfManager::PerfManager()
- {
- mRecording = false;
- mCurStackIdx = 0;
- mOwningThreadId = 0;
- mOverhead = 0;
- mAlloc.mDisableDebugTracing = true;
- }
- void PerfManager::NextFrame()
- {
- if (!mRecording)
- return;
- BF_ASSERT(mCurStackIdx <= 1);
- while (mCurStackIdx > 0)
- ZoneEnd(true);
- auto logEntryFrameStart = mAlloc.Alloc<PerfLogEntry_FrameStart>();
- logEntryFrameStart->mType = PerfLogEntryType_FrameStart;
- logEntryFrameStart->mTimingStart = BFGetTickCountMicroFast();
- mLogEntries.PushBack(logEntryFrameStart);
- mCurStackIdx++;
- }
- void PerfManager::ZoneStart(const char* name)
- {
- if (!mRecording)
- return;
- #ifdef PERF_WANTS_THREAD_CHECK
- BF_ASSERT(mOwningThreadId == BfpThread_GetCurrentId());
- #endif
-
- uint64 callTimerStart = BFGetTickCountMicroFast();
- mCurStackIdx++;
- int nameLen = (int)strlen(name);
- auto logEntryStart = mAlloc.Alloc<PerfLogEntry_Start>(nameLen + 1);
- char* namePtr = (char*)(logEntryStart + 1);
- strcpy(namePtr, name);
- logEntryStart->mType = PerfLogEntryType_Start;
- logEntryStart->mName = namePtr;
- mLogEntries.PushBack(logEntryStart);
- logEntryStart->mTimingStart = BFGetTickCountMicroFast();;
- mOverhead += logEntryStart->mTimingStart - callTimerStart;
- /*
- if (mCurStackIdx == 0)
- GetCurFrame();
- PerfEntry* curParent = mCurStack[mCurStackIdx - 1];
- PerfEntry* entry = NULL;
- if (curParent->mChild != NULL)
- {
- if (curParent->mChild->mName == name)
- entry = curParent->mChild;
- }
- if (entry == NULL)
- {
- PerfEntryMap::iterator itr = curParent->mChildren.find(name);
-
- if (itr != curParent->mChildren.end())
- {
- entry = &itr->second;
- }
- else
- {
- itr = curParent->mChildren.insert(PerfEntryMap::value_type(name, PerfEntry())).first;
- entry = &itr->second;
- entry->mName = name;
- }
- curParent->mChild = entry;
- }
- entry->mCount++;
- entry->mCurTimingStart = BFGetTickCountMicroFast();
- mCurStack[mCurStackIdx++] = entry;
- mOverhead += entry->mCurTimingStart - callTimerStart;*/
- }
- void PerfManager::ZoneEnd(bool allowFrameEnd)
- {
- if (!mRecording)
- return;
-
- if ((mCurStackIdx <= 1) && (!allowFrameEnd))
- return;
-
- auto logEntryEnd = mAlloc.Alloc<PerfLogEntry_End>();
- logEntryEnd->mType = PerfLogEntryType_End;
- logEntryEnd->mTimingEnd = BFGetTickCountMicroFast();
- mLogEntries.PushBack(logEntryEnd);
- mCurStackIdx--;
- /*PerfEntry* entry = mCurStack[mCurStackIdx - 1];
- mCurStackIdx--;
- entry->mTimeTotal += BFGetTickCountMicroFast() - entry->mCurTimingStart;*/
- }
- void PerfManager::Message(const StringImpl& theString)
- {
- if (!mRecording)
- return;
- //TODO: Implement
- /*if (mCurStackIdx == 0)
- GetCurFrame();
- PerfEntry* entry = mCurStack[mCurStackIdx - 1];
- PerfLogEntry logEntry;
- logEntry.mTick = BFTickCount();
- logEntry.mString = theString;
- entry->mLog.push_back(logEntry);*/
- }
- void PerfManager::StartRecording()
- {
- #ifdef PERF_WANTS_THREAD_CHECK
- mOwningThreadId = BfpThread_GetCurrentId();
- #endif
- mRecording = true;
- Clear();
- NextFrame();
- }
- void PerfManager::StopRecording(bool dbgPrint)
- {
- if (!mRecording)
- return;
- #ifdef PERF_WANTS_THREAD_CHECK
- BF_ASSERT(mOwningThreadId == ::BfpThread_GetCurrentId());
- #endif
- mRecording = false;
-
- auto logEntryStopRecording = mAlloc.Alloc<PerfLogEntry_StopRecording>();
- logEntryStopRecording->mType = PerfLogEntryType_StopRecording;
- logEntryStopRecording->mTimingEnd = BFGetTickCountMicroFast();
- mLogEntries.PushBack(logEntryStopRecording);
- if (dbgPrint)
- DbgPrint();
- /*if (mFrames.size() > 0)
- {
- PerfFrame* frame = &mFrames.back();
- frame->mTimeTotal = BFGetTickCountMicroFast() - frame->mCurTimingStart;
- }*/
- }
- bool PerfManager::IsRecording()
- {
- return mRecording;
- }
- void PerfManager::DbgPrint()
- {
- #ifdef PERF_WANTS_THREAD_CHECK
- BF_ASSERT(mOwningThreadId == ::BfpThread_GetCurrentId());
- #endif
- if (mFrames.empty())
- {
- mCurStackIdx = 0;
- PerfFrame* curFrame = NULL;
- for (auto logEntry : mLogEntries)
- {
- if (logEntry->mType == PerfLogEntryType_FrameStart)
- {
- PerfLogEntry_FrameStart* frameStartEntry = (PerfLogEntry_FrameStart*)logEntry;
- if (mFrames.size() > 0)
- {
- PerfFrame* frame = &mFrames.back();
- frame->mTimeTotal = frameStartEntry->mTimingStart - frame->mCurTimingStart;
- }
- mFrames.push_back(PerfFrame());
- PerfFrame* frame = &mFrames.back();
- frame->mCurTimingStart = frameStartEntry->mTimingStart;
- #ifndef BF_NO_BFAPP
- if (gBFApp != NULL)
- frame->mAppFrameNum = gBFApp->mUpdateCnt;
- else
- frame->mAppFrameNum = 0;
- #else
- frame->mAppFrameNum = 0;
- #endif
- frame->mCount = 1;
- mCurStack[mCurStackIdx++] = frame;
- }
- else if (logEntry->mType == PerfLogEntryType_Start)
- {
- PerfLogEntry_Start* entryStart = (PerfLogEntry_Start*)logEntry;
- PerfEntry* curParent = mCurStack[mCurStackIdx - 1];
-
- PerfEntry* entry = NULL;
- if (curParent->mChild != NULL)
- {
- if (curParent->mChild->mName == entryStart->mName)
- entry = curParent->mChild;
- }
- if (entry == NULL)
- {
- /*PerfEntryMap::iterator itr = curParent->mChildren.find(entryStart->mName);
- if (itr != curParent->mChildren.end())
- {
- entry = &itr->second;
- }
- else
- {
- itr = curParent->mChildren.insert(PerfEntryMap::value_type(entryStart->mName, PerfEntry())).first;
- entry = &itr->second;
- entry->mName = entryStart->mName;
- }*/
- PerfEntry** entryPtr = NULL;
- if (curParent->mChildren.TryAdd(entryStart->mName, NULL, &entryPtr))
- {
- entry = mAlloc.Alloc<PerfEntry>();
- *entryPtr = entry;
- entry->mName = entryStart->mName;
- }
- else
- {
- entry = *entryPtr;
- }
- curParent->mChild = entry;
- }
- entry->mCount++;
- entry->mCurTimingStart = entryStart->mTimingStart;
- mCurStack[mCurStackIdx++] = entry;
- }
- else if (logEntry->mType == PerfLogEntryType_End)
- {
- PerfLogEntry_End* entryEnd = (PerfLogEntry_End*)logEntry;
- PerfEntry* entry = mCurStack[mCurStackIdx - 1];
- mCurStackIdx--;
- entry->mTimeTotal += entryEnd->mTimingEnd - entry->mCurTimingStart;
- }
- else if (logEntry->mType == PerfLogEntryType_StopRecording)
- {
- PerfLogEntry_StopRecording* stopRecordingEntry = (PerfLogEntry_StopRecording*)logEntry;
- if (mFrames.size() > 0)
- {
- PerfFrame* frame = &mFrames.back();
- frame->mTimeTotal = stopRecordingEntry->mTimingEnd - frame->mCurTimingStart;
- }
- }
- }
- }
- std::map<String, int> uniqueTimingMap;
- OutputDebugStrF("PerfManager_Results____________________________________________________________Calls___MSTotal__MSSelf\n");
- PerfFrameList::iterator frameItr = mFrames.begin();
- while (frameItr != mFrames.end())
- {
- PerfFrame* frame = &(*frameItr);
- frame->DbgPrint(StrFormat("Frame %d", frame->mAppFrameNum), 0, uniqueTimingMap);
- ++frameItr;
- }
- OutputDebugStr("\nPerfManager_Combined_Results____________________________________________________________________MSSelf\n");
- typedef std::multimap<int, String> SortedMap;
- SortedMap sortedMap;
- for (auto& entry : uniqueTimingMap)
- {
- sortedMap.insert(SortedMap::value_type(-entry.second, entry.first));
- }
- for (auto& entry : sortedMap)
- {
- String text = entry.second;
- for (int i = (int)text.length(); i < 96; i++)
- text += " ";
- text += StrFormat("%6.1f\n", -entry.first / 1000.0f);
- OutputDebugStr(text.c_str());
- }
- {
- String text = "PerfTimer Timing Overhead";
- for (int i = (int) text.length(); i < 96; i++)
- text += " ";
- text += StrFormat("%6.1f\n", mOverhead / 1000.0f);
- OutputDebugStr(text.c_str());
- }
- }
- AutoPerf::AutoPerf(const char* name, PerfManager* perfManager)
- {
- if ((perfManager == NULL) || (!perfManager->mRecording))
- {
- mPerfManager = NULL;
- mStartStackIdx = 0;
- return;
- }
- mPerfManager = perfManager;
- mPerfManager->ZoneStart(name);
- mStartStackIdx = mPerfManager->mCurStackIdx - 1;
- }
- void AutoPerf::Leave()
- {
- if (mStartStackIdx <= 0)
- return;
- BF_ASSERT(mPerfManager->mCurStackIdx <= mStartStackIdx + 1);
- if (mPerfManager->mCurStackIdx > mStartStackIdx)
- mPerfManager->ZoneEnd();
- mStartStackIdx = -1;
- }
- AutoPerf::~AutoPerf()
- {
- Leave();
- }
- //////////////////////////////////////////////////////////////////////////
- AutoPerfRecordAndPrint::AutoPerfRecordAndPrint(PerfManager* perfManager)
- {
- mPerfManager = perfManager;
- mDidStart = !perfManager->mRecording;
- if (mDidStart)
- perfManager->StartRecording();
- }
- AutoPerfRecordAndPrint::~AutoPerfRecordAndPrint()
- {
- if (mDidStart)
- mPerfManager->StopRecording(true);
- }
- //////////////////////////////////////////////////////////////////////////
- AutoDbgTime::AutoDbgTime(const StringImpl& name)
- {
- mName = name;
- mStartTick = BFTickCount();
- }
- AutoDbgTime::~AutoDbgTime()
- {
- int totalTime = BFTickCount() - mStartTick;
- OutputDebugStrF("%s: %d\n", mName.c_str(), totalTime);
- }
- ///
- #ifdef BFSYSLIB_DYNAMIC
- BF_EXPORT void BF_CALLTYPE PerfTimer_ZoneStart(const char* name)
- {
- gPerfManager->ZoneStart(name);
- }
- BF_EXPORT void BF_CALLTYPE PerfTimer_ZoneEnd()
- {
- gPerfManager->ZoneEnd();
- }
- BF_EXPORT void BF_CALLTYPE PerfTimer_Message(const char* theString)
- {
- gPerfManager->Message(theString);
- }
- BF_EXPORT int BF_CALLTYPE PerfTimer_IsRecording()
- {
- return gPerfManager->IsRecording() ? 1 : 0;
- }
- BF_EXPORT void BF_CALLTYPE PerfTimer_StartRecording()
- {
- gPerfManager->StartRecording();
- }
- BF_EXPORT void BF_CALLTYPE PerfTimer_StopRecording()
- {
- gPerfManager->StopRecording();
- }
- BF_EXPORT void BF_CALLTYPE PerfTimer_DbgPrint()
- {
- gPerfManager->DbgPrint();
- }
- #endif
|