148 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| //-----------------------------------------------------------------------------
 | |
| // Torque Game Engine
 | |
| // Copyright (C) GarageGames.com, Inc.
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| #ifndef _PROFILER_H_
 | |
| #define _PROFILER_H_
 | |
| 
 | |
| #include "core/torqueConfig.h"
 | |
| 
 | |
| #ifdef TORQUE_ENABLE_PROFILER
 | |
| 
 | |
| struct ProfilerData;
 | |
| struct ProfilerRootData;
 | |
| /// The Profiler is used to see how long a specific chunk of code takes to execute.
 | |
| /// All values outputted by the profiler are percentages of the time that it takes
 | |
| /// to run entire main loop.
 | |
| ///
 | |
| /// First, you must #define TORQUE_ENABLE_PROFILER in profiler.h in order to
 | |
| /// active it.  Examples of script use:
 | |
| /// @code
 | |
| /// //enables or disables profiling.  Data is only gathered when the profiler is enabled.
 | |
| /// profilerEnable(bool enable);
 | |
| /// profilerReset();                                        //resets the data gathered by the profiler
 | |
| /// profilerDump();                                         //dumps all profiler data to the console
 | |
| /// profilerDumpToFile(string filename);                    //dumps all profiler data to a given file
 | |
| /// profilerMarkerEnable((string markerName, bool enable);  //enables or disables a given profile tag
 | |
| /// @endcode
 | |
| ///
 | |
| /// The C++ code side of the profiler uses pairs of PROFILE_START() and PROFILE_END().
 | |
| ///
 | |
| /// When using these macros, make sure there is a PROFILE_END() for every PROFILE_START
 | |
| /// and a PROFILE_START() for every PROFILE_END().  It is fine to nest these macros, however,
 | |
| /// you must make sure that no matter what execution path the code takes, the PROFILE macros
 | |
| /// will be balanced.
 | |
| ///
 | |
| /// The profiler can be used to locate areas of code that are slow or should be considered for
 | |
| /// optimization.  Since it tracks the relative time of execution of that code to the execution
 | |
| /// of the main loop, it is possible to benchmark any given code to see if changes made will
 | |
| /// actually improve performance.
 | |
| ///
 | |
| /// Here are some examples:
 | |
| /// @code
 | |
| /// PROFILE_START(TerrainRender);
 | |
| /// //some code here
 | |
| /// PROFILE_START(TerrainRenderGridSquare);
 | |
| /// //some code here
 | |
| /// PROFILE_END();
 | |
| /// //possibly some code here
 | |
| /// PROFILE_END();
 | |
| /// @endcode
 | |
| class Profiler
 | |
| {
 | |
|    enum {
 | |
|       MaxStackDepth = 256,
 | |
|       DumpFileNameLength = 256
 | |
|    };
 | |
|    U32 mCurrentHash;
 | |
| 
 | |
|    ProfilerData *mCurrentProfilerData;
 | |
|    ProfilerData *mProfileList;
 | |
|    ProfilerData *mRootProfilerData;
 | |
| 
 | |
|    bool mEnabled;
 | |
|    S32 mStackDepth;
 | |
|    bool mNextEnable;
 | |
|    U32 mMaxStackDepth;
 | |
|    bool mDumpToConsole;
 | |
|    bool mDumpToFile;
 | |
|    char mDumpFileName[DumpFileNameLength];
 | |
|    void dump();
 | |
|    void validate();
 | |
| public:
 | |
|    Profiler();
 | |
|    ~Profiler();
 | |
| 
 | |
|    /// Reset the data in the profiler
 | |
|    void reset();
 | |
|    /// Dumps the profile to console
 | |
|    void dumpToConsole();
 | |
|    /// Dumps the profile data to a file
 | |
|    /// @param fileName filename to dump data to
 | |
|    void dumpToFile(const char *fileName);
 | |
|    /// Enable profiling
 | |
|    void enable(bool enabled);
 | |
|    /// Helper function for macro definition PROFILE_START
 | |
|    void hashPush(ProfilerRootData *data);
 | |
|    /// Helper function for macro definition PROFILE_END
 | |
|    void hashPop();
 | |
|    /// Enable a profiler marker
 | |
|    void enableMarker(const char *marker, bool enabled);
 | |
| };
 | |
| 
 | |
| extern Profiler *gProfiler;
 | |
| 
 | |
| struct ProfilerRootData
 | |
| {
 | |
|    const char *mName;
 | |
|    U32 mNameHash;
 | |
|    ProfilerData *mFirstProfilerData;
 | |
|    ProfilerRootData *mNextRoot;
 | |
|    F64 mTotalTime;
 | |
|    F64 mSubTime;
 | |
|    U32 mTotalInvokeCount;
 | |
|    bool mEnabled;
 | |
| 
 | |
|    static ProfilerRootData *sRootList;
 | |
| 
 | |
|    ProfilerRootData(const char *name);
 | |
| };
 | |
| 
 | |
| struct ProfilerData
 | |
| {
 | |
|    ProfilerRootData *mRoot; ///< link to root node.
 | |
|    ProfilerData *mNextForRoot; ///< links together all ProfilerData's for a particular root
 | |
|    ProfilerData *mNextProfilerData; ///< links all the profilerDatas
 | |
|    ProfilerData *mNextHash;
 | |
|    ProfilerData *mParent;
 | |
|    ProfilerData *mNextSibling;
 | |
|    ProfilerData *mFirstChild;
 | |
|    enum {
 | |
|       HashTableSize = 32,
 | |
|    };
 | |
|    ProfilerData *mChildHash[HashTableSize];
 | |
|    ProfilerData *mLastSeenProfiler;
 | |
| 
 | |
|    U32 mHash;
 | |
|    U32 mSubDepth;
 | |
|    U32 mInvokeCount;
 | |
|    U32 mStartTime[2];
 | |
|    F64 mTotalTime;
 | |
|    F64 mSubTime;
 | |
| };
 | |
| 
 | |
| 
 | |
| #define PROFILE_START(name) \
 | |
| static ProfilerRootData pdata##name##obj (#name); \
 | |
| if(gProfiler) gProfiler->hashPush(& pdata##name##obj )
 | |
| 
 | |
| #define PROFILE_END() if(gProfiler) gProfiler->hashPop()
 | |
| 
 | |
| #else
 | |
| #define PROFILE_START(x)
 | |
| #define PROFILE_END()
 | |
| #endif
 | |
| 
 | |
| #endif
 | 
