Files
FC1/CrySystem/CrySizerStats.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

183 lines
5.7 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// 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 <sergiy@crytek.de>
//
//////////////////////////////////////////////////////////////////////
#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<Component> 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<size_t> 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