You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
7.1 KiB
C++
208 lines
7.1 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
// Description : 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.
|
|
|
|
#ifndef CRYINCLUDE_CRYSYSTEM_CRYSIZERSTATS_H
|
|
#define CRYINCLUDE_CRYSYSTEM_CRYSIZERSTATS_H
|
|
#pragma once
|
|
|
|
|
|
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 getSizeKBytes() const {return sizeBytes / float(1 << 10); }
|
|
|
|
float getTotalSizeKBytes () const {return sizeBytesTotal / float(1 << 10); }
|
|
|
|
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); }
|
|
|
|
unsigned row() const {return m_nStartRow; }
|
|
void updateKeys();
|
|
|
|
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;
|
|
|
|
//current row offset inc/dec by cursor keys
|
|
unsigned m_nStartRow;
|
|
|
|
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:
|
|
// constructor
|
|
CrySizerStatsRenderer (ISystem* pSystem, CrySizerStats* pStats, unsigned nMaxDepth = 2, int nMinSubcomponentBytes = -1);
|
|
void render(bool bRefreshMark = false);
|
|
// dumps it to log. uses MB as default
|
|
void dump (bool bUseKB = false);
|
|
|
|
protected: // -------------------------------------------------
|
|
|
|
typedef CrySizerStats::Component Component;
|
|
|
|
IRenderer* m_pRenderer; //
|
|
ILog* m_pLog; //
|
|
CrySizerStats* m_pStats; //
|
|
|
|
ITextModeConsole* m_pTextModeConsole;
|
|
|
|
// 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 // CRYINCLUDE_CRYSYSTEM_CRYSIZERSTATS_H
|