////////////////////////////////////////////////////////////////////// // // CryEngine Source code // // File:CrySizerStats.h // Declaration of the CrySizerStats class, which is used to // calculate the memory usage by the subsystems and components, to help // the artists keep the memory budged low. // // // History: // December 03, 2002 : Created by Sergiy Migdalskiy // ////////////////////////////////////////////////////////////////////// #ifndef _CRY_SYSTEM_CRY_SIZER_STATS_HDR_ #define _CRY_SYSTEM_CRY_SIZER_STATS_HDR_ class CrySizerImpl; ////////////////////////////////////////////////////////////////////////// // This class holds only the necessary statistics data, which can be carried // over a few frames without significant impact on memory usage // CrySizerImpl is an implementation of ICrySizer, which is used to collect // those data; it must be destructed immediately after constructing the Stats // object to avoid excessive memory usage. class CrySizerStats { public: // constructs the statistics based on the given cry sizer CrySizerStats (CrySizerImpl* pCrySizer); CrySizerStats (); // this structure describes one component of the memory size statistics struct Component { Component() {clear();} Component (const string& name, unsigned size = 0, unsigned num = 0): strName(name), sizeBytes(size), numObjects(num), nDepth(0) {} void clear() { strName = ""; sizeBytes = 0; numObjects = 0; nDepth = 0; } // the name of the component, as it appeared in the push() call string strName; // the total size, in bytes, of objects in the component size_t sizeBytes; // the total size including the subcomponents size_t sizeBytesTotal; // the number of objects allocated size_t numObjects; unsigned nDepth; float getSizeMBytes() const {return sizeBytes / float(1<<20);} float getTotalSizeMBytes () const {return sizeBytesTotal / float(1<<20);} struct NameOrder { bool operator () (const Component& left, const Component& right)const {return left.strName < right.strName;} }; struct SizeOrder { bool operator () (const Component& left, const Component& right)const {return left.sizeBytes < right.sizeBytes;} }; struct GenericOrder { bool operator () (const Component& left, const Component& right)const; }; }; // returns the number of different subsystems/components used unsigned numComponents()const {return (unsigned)m_arrComponents.size();} // returns the name of the i-th component const Component& getComponent(unsigned nComponent)const {return m_arrComponents[nComponent];} unsigned size() const {return numComponents();} const Component& operator [] (unsigned i) const {return getComponent(i);} const Component& operator [] ( signed i) const {return getComponent(i);} size_t getMaxNameLength()const {return m_nMaxNameLength;} enum {g_numTimers = 3}; void startTimer(unsigned nTimer, ITimer*pTimer); void stopTimer(unsigned nTimer, ITimer*pTimer); float getTime(unsigned nTimer)const {assert (nTimer < g_numTimers);return m_fTime[nTimer];} int getAgeFrames() const {return m_nAgeFrames;} void incAgeFrames() {++m_nAgeFrames;} protected: // refreshes the statistics built after the component array is built void refresh(); protected: // the names of the components typedef std::vector ComponentArray; ComponentArray m_arrComponents; // the maximum length of the component name, in characters size_t m_nMaxNameLength; // the timer that counts the time spent on statistics gathering float m_fTime[g_numTimers]; // the age of the statistics, in frames int m_nAgeFrames; friend class CrySizerStatsBuilder; }; ////////////////////////////////////////////////////////////////////////// // this is the constructor for the CrySizerStats class CrySizerStatsBuilder { public: CrySizerStatsBuilder (CrySizerImpl* pSizer, int nMinSubcomponentBytes = 0); void build (CrySizerStats* pStats); protected: typedef CrySizerStats::Component Component; // if there is already such name in the map, then just returns the index // of the compoentn in the component array; otherwise adds an entry to themap // and to the component array nad returns its index Component& mapName (unsigned nName); // creates the map of names from old to new, and initializes the components themselves void processNames(); // given the name in the old system, adds the subtree of names to the // name map and components. In case all the subtree is empty, returns 0 and // adds nothing. Otherwise, returns the total size of objects belonging to the // subtree size_t addNameSubtree (unsigned nDepth, size_t nName); protected: CrySizerStats* m_pStats; CrySizerImpl* m_pSizer; // this is the mapping from the old names into the new componentn indices typedef std::vector IdToIdMap; // from old to new IdToIdMap m_mapNames; // this is the threshold: if the total number of bytes in the subcomponent // is less than this, the subcomponent isn't shown unsigned m_nMinSubcomponentBytes; }; ////////////////////////////////////////////////////////////////////////// // Renders the given usage stats; gets created upon every rendering class CrySizerStatsRenderer { public: CrySizerStatsRenderer (ISystem* pSystem, CrySizerStats* pStats, unsigned nMaxDepth = 2, int nMinSubcomponentBytes = -1); void render(bool bRefreshMark = false); // dumps it to log void dump (); protected: typedef CrySizerStats::Component Component; IRenderer* m_pRenderer; ILog* m_pLog; CrySizerStats* m_pStats; class CXFont* m_pFont; // this is the threshold: if the total number of bytes in the subcomponent // is less than this, the subcomponent isn't shown unsigned m_nMinSubcomponentBytes; // the max depth of the branch to output unsigned m_nMaxSubcomponentDepth; }; #endif