/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : WWDebug * * * * $Archive:: /Commando/Code/wwdebug/wwprofile.h $* * * * $Author:: Jani_p $* * * * $Modtime:: 3/25/02 2:05p $* * * * $Revision:: 14 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 //#define ENABLE_TIME_AND_MEMORY_LOG #ifndef WWPROFILE_H #define WWPROFILE_H #include "wwstring.h" #ifdef _UNIX typedef signed long long __int64; typedef signed long long _int64; #endif // enable profiling by default in debug mode. #ifdef WWDEBUG #define ENABLE_WWPROFILE #endif extern unsigned WWProfile_Get_System_Time(); // timeGetTime() wrapper class FileClass; /* ** A node in the WWProfile Hierarchy Tree */ class WWProfileHierachyNodeClass { public: WWProfileHierachyNodeClass( const char * name, WWProfileHierachyNodeClass * parent ); ~WWProfileHierachyNodeClass( void ); WWProfileHierachyNodeClass * Get_Sub_Node( const char * name ); WWProfileHierachyNodeClass * Get_Parent( void ) { return Parent; } WWProfileHierachyNodeClass * Get_Sibling( void ) { return Sibling; } WWProfileHierachyNodeClass * Get_Child( void ) { return Child; } void Reset( void ); void Call( void ); bool Return( void ); const char * Get_Name( void ) { return Name; } int Get_Total_Calls( void ) { return TotalCalls; } float Get_Total_Time( void ) { return TotalTime; } WWProfileHierachyNodeClass* Clone_Hierarchy(WWProfileHierachyNodeClass* parent); void Write_To_File(FileClass* file,int recursion); int Get_Total_Calls() const { return TotalCalls; } float Get_Total_Time() const { return TotalTime; } void Set_Total_Calls(int calls) { TotalCalls=calls; } void Set_Total_Time(float time) { TotalTime=time; } protected: const char * Name; int TotalCalls; float TotalTime; __int64 StartTime; int RecursionCounter; WWProfileHierachyNodeClass * Parent; WWProfileHierachyNodeClass * Child; WWProfileHierachyNodeClass * Sibling; }; /* ** An iterator to navigate through the tree */ class WWProfileIterator { public: // Access all the children of the current parent void First(void); void Next(void); bool Is_Done(void); void Enter_Child( void ); // Make the current child the new parent void Enter_Child( int index ); // Make the given child the new parent void Enter_Parent( void ); // Make the current parent's parent the new parent // Access the current child const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } // Access the current parent const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } protected: WWProfileHierachyNodeClass * CurrentParent; WWProfileHierachyNodeClass * CurrentChild; WWProfileIterator( WWProfileHierachyNodeClass * start ); friend class WWProfileManager; }; /* ** An iterator to walk through the tree in depth first order */ class WWProfileInOrderIterator { public: void First(void); void Next(void); bool Is_Done(void); // Access the current node const char * Get_Current_Name( void ) { return CurrentNode->Get_Name(); } int Get_Current_Total_Calls( void ) { return CurrentNode->Get_Total_Calls(); } float Get_Current_Total_Time( void ) { return CurrentNode->Get_Total_Time(); } protected: WWProfileHierachyNodeClass * CurrentNode; WWProfileInOrderIterator( void ); friend class WWProfileManager; }; /* ** The Manager for the WWProfile system */ class WWProfileManager { public: static void Start_Profile( const char * name ); static void Stop_Profile( void ); static void Start_Root_Profile( const char * name ); static void Stop_Root_Profile( void ); static void Reset( void ); static void Increment_Frame_Counter( void ); static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } static float Get_Time_Since_Reset( void ); static WWProfileIterator * Get_Iterator( void ); static void Release_Iterator( WWProfileIterator * iterator ); static WWProfileInOrderIterator * Get_In_Order_Iterator( void ); static void Release_In_Order_Iterator( WWProfileInOrderIterator * iterator ); static WWProfileHierachyNodeClass * Get_Root( void ) { return &Root; } static void Begin_Collecting(); static void End_Collecting(const char* filename); private: static WWProfileHierachyNodeClass Root; static WWProfileHierachyNodeClass * CurrentNode; static WWProfileHierachyNodeClass * CurrentRootNode; static int FrameCounter; static __int64 ResetTime; friend class WWProfileInOrderIterator; }; /* ** WWProfileSampleClass is a simple way to profile a function's scope ** Use the WWPROFILE macro at the start of scope to time */ class WWProfileSampleClass { bool IsRoot; public: WWProfileSampleClass( const char * name, bool is_root ) : IsRoot(is_root) { if (IsRoot) WWProfileManager::Start_Root_Profile( name ); else WWProfileManager::Start_Profile( name ); } ~WWProfileSampleClass( void ) { if (IsRoot) WWProfileManager::Stop_Root_Profile(); else WWProfileManager::Stop_Profile(); } }; #ifdef ENABLE_WWPROFILE #define WWPROFILE( name ) WWProfileSampleClass _wwprofile( name, false ) #define WWROOTPROFILE( name ) WWProfileSampleClass _wwprofile( name, true ) #else #define WWPROFILE( name ) #define WWROOTPROFILE( name ) #endif /* ** WWTimeIt is like WWProfile, but it doesn't save anything, it just times one routine, regardless of thread */ class WWTimeItClass { public: WWTimeItClass( const char * name ); ~WWTimeItClass( void ); private: const char * Name; __int64 Time; }; #ifdef ENABLE_WWPROFILE #define WWTIMEIT( name ) WWTimeItClass _wwtimeit( name ) #else #define WWTIMEIT( name ) #endif /* ** TSS 06/27/01 ** WWMeasureItClass is like WWTimeItClass, but it pokes the result into the given float, ** and can be used in the release build. */ class WWMeasureItClass { public: WWMeasureItClass( float * p_result ); ~WWMeasureItClass( void ); private: __int64 Time; float * PResult; }; // ---------------------------------------------------------------------------- // // Use the first macro to log time and memory usage within the stack segment. // Use the second macro to log intermediate values. The intermediate values are // calculated from the previous intermediate log, so you can log how much each // item takes by placing the macro after each of the // // ---------------------------------------------------------------------------- #ifdef ENABLE_TIME_AND_MEMORY_LOG #define WWLOG_PREPARE_TIME_AND_MEMORY(t) WWMemoryAndTimeLog memory_and_time_log(t) #define WWLOG_INTERMEDIATE(t) memory_and_time_log.Log_Intermediate(t) #else #define WWLOG_PREPARE_TIME_AND_MEMORY(t) #define WWLOG_INTERMEDIATE(t) #endif struct WWMemoryAndTimeLog { unsigned TimeStart; unsigned IntermediateTimeStart; int AllocCountStart; int IntermediateAllocCountStart; int AllocSizeStart; int IntermediateAllocSizeStart; StringClass Name; static unsigned TabCount; WWMemoryAndTimeLog(const char* name); ~WWMemoryAndTimeLog(); void Log_Intermediate(const char* text); }; #endif // WWPROFILE_H