#pragma once #include "../Common.h" //#include "boost/unordered/unordered_map.hpp" #include "BumpAllocator.h" #include "SLIList.h" #include #include "BumpAllocator.h" #include "Dictionary.h" #include #include NS_BF_BEGIN; class PerfEntry; class PerfEntry { public: String mName; Dictionary mChildren; PerfEntry* mChild; int mCount; uint64 mTimeTotal; uint64 mCurTimingStart; public: PerfEntry(); void DbgPrint(const StringImpl& name, int level, std::map& uniqueTimingMap); }; class PerfFrame : public PerfEntry { public: int mAppFrameNum; }; typedef std::list PerfFrameList; const int MAX_PERFMANGER_STACKSIZE = 256; enum PerfLogEntryType { PerfLogEntryType_FrameStart, PerfLogEntryType_Start, PerfLogEntryType_End, PerfLogEntryType_Log, PerfLogEntryType_StopRecording }; struct PerfLogEntry { int mType; PerfLogEntry* mNext; }; struct PerfLogEntry_FrameStart : PerfLogEntry { uint64 mTimingStart; }; struct PerfLogEntry_StopRecording : PerfLogEntry { uint64 mTimingEnd; }; // We could use 32-bit timing start and timing end values and still // record timings up to 71 minutes long struct PerfLogEntry_Start : PerfLogEntry { const char* mName; uint64 mTimingStart; }; struct PerfLogEntry_End : PerfLogEntry { uint64 mTimingEnd; }; class PerfManager { public: BumpAllocator mAlloc; SLIList mLogEntries; PerfFrameList mFrames; PerfEntry* mCurStack[MAX_PERFMANGER_STACKSIZE]; int mCurStackIdx; bool mRecording; BfpThreadId mOwningThreadId; uint64 mOverhead; protected: void Clear(); public: PerfManager(); void NextFrame(); void ZoneStart(const char* name); void ZoneEnd(bool allowFrameEnd = false); void Message(const StringImpl& theString); void StartRecording(); void StopRecording(bool dbgPrint = false); bool IsRecording(); void DbgPrint(); }; extern PerfManager* gPerfManager; class AutoPerf { public: PerfManager* mPerfManager; int mStartStackIdx; public: AutoPerf(const char* name, PerfManager* perfManager = gPerfManager); ~AutoPerf(); void Leave(); }; class AutoDbgTime { public: uint32 mStartTick; String mName; public: AutoDbgTime(const StringImpl& name); ~AutoDbgTime(); }; class AutoPerfRecordAndPrint { public: PerfManager* mPerfManager; bool mDidStart; public: AutoPerfRecordAndPrint(PerfManager* perfManager = gPerfManager); ~AutoPerfRecordAndPrint(); }; class AutoTimer { public: uint32 mStartTick; int* mTimePtr; public: AutoTimer(int& timeRef) { mTimePtr = &timeRef; mStartTick = BFTickCount(); } ~AutoTimer() { *mTimePtr += BFTickCount() - mStartTick; } }; class DebugTimeGuard { public: uint32 mStartTick; int mMaxTicks; String mName; public: DebugTimeGuard(int maxTicks, const StringImpl& name = StringImpl::MakeRef("DebugTimeGuard")) { mName = name; mMaxTicks = maxTicks; Start(); } void Start() { mStartTick = BFTickCount(); } void Stop() { if (mMaxTicks == 0) return; int maxTime = (int)(BFTickCount() - mStartTick); if (maxTime > mMaxTicks) OutputDebugStrF("%s took too long: %dms\n", mName.c_str(), maxTime); mMaxTicks = 0; } ~DebugTimeGuard() { Stop(); } }; NS_BF_END;