forked from 0ad/0ad
# Added primitive memory-allocation counting
Profiler: now shows "mem allocs" for the previous frame (only in MSVC Debug mode). Aura: got rid of a couple of hundred allocations per frame. This was SVN commit r4805.
This commit is contained in:
parent
ff52db91fa
commit
5c8250ddb8
@ -13,6 +13,7 @@
|
||||
#include "graphics/UnitManager.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "lib/sdl.h"
|
||||
#include "lib/timer.h"
|
||||
#include "network/NetMessage.h"
|
||||
#include "ps/Game.h"
|
||||
#include "ps/Interact.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "Profile.h"
|
||||
#include "ProfileViewer.h"
|
||||
|
||||
#include "lib/timer.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CProfileNodeTable
|
||||
@ -57,6 +57,7 @@ private:
|
||||
columns.push_back(ProfileColumn("msec/frame", 100));
|
||||
columns.push_back(ProfileColumn("%/frame", 100));
|
||||
columns.push_back(ProfileColumn("%/parent", 100));
|
||||
columns.push_back(ProfileColumn("mem allocs", 100));
|
||||
}
|
||||
};
|
||||
|
||||
@ -115,7 +116,7 @@ CStr CProfileNodeTable::GetCellText(size_t row, size_t col)
|
||||
CProfileNode* child;
|
||||
size_t nrchildren = node->GetChildren()->size();
|
||||
size_t nrscriptchildren = node->GetScriptChildren()->size();
|
||||
char buf[256];
|
||||
char buf[256] = "?";
|
||||
|
||||
if (row < nrchildren)
|
||||
child = (*node->GetChildren())[row];
|
||||
@ -132,19 +133,28 @@ CStr CProfileNodeTable::GetCellText(size_t row, size_t col)
|
||||
return "";
|
||||
|
||||
float unlogged = node->GetFrameTime();
|
||||
long unlogged_mallocs = node->GetFrameMallocs();
|
||||
CProfileNode::const_profile_iterator it;
|
||||
|
||||
for(it = node->GetChildren()->begin(); it != node->GetChildren()->end(); ++it)
|
||||
for (it = node->GetChildren()->begin(); it != node->GetChildren()->end(); ++it)
|
||||
{
|
||||
unlogged -= (*it)->GetFrameTime();
|
||||
for(it = node->GetScriptChildren()->begin(); it != node->GetScriptChildren()->end(); ++it)
|
||||
unlogged_mallocs -= (*it)->GetFrameMallocs();
|
||||
}
|
||||
for (it = node->GetScriptChildren()->begin(); it != node->GetScriptChildren()->end(); ++it)
|
||||
{
|
||||
unlogged -= (*it)->GetFrameTime();
|
||||
unlogged_mallocs -= (*it)->GetFrameMallocs();
|
||||
}
|
||||
|
||||
if (col == 2)
|
||||
snprintf(buf, sizeof(buf), "%.3f", unlogged * 1000.0f);
|
||||
else if (col == 3)
|
||||
snprintf(buf, sizeof(buf), "%.1f", unlogged / g_Profiler.GetRoot()->GetFrameTime());
|
||||
else
|
||||
else if (col == 4)
|
||||
snprintf(buf, sizeof(buf), "%.1f", unlogged * 100.0f / g_Profiler.GetRoot()->GetFrameTime());
|
||||
else if (col == 5)
|
||||
snprintf(buf, sizeof(buf), "%d", unlogged_mallocs);
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
|
||||
return CStr(buf);
|
||||
@ -172,6 +182,9 @@ CStr CProfileNodeTable::GetCellText(size_t row, size_t col)
|
||||
case 4:
|
||||
snprintf(buf, sizeof(buf), "%.1f", child->GetFrameTime() * 100.0 / node->GetFrameTime());
|
||||
break;
|
||||
case 5:
|
||||
snprintf(buf, sizeof(buf), "%d", child->GetFrameMallocs());
|
||||
break;
|
||||
}
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
return CStr(buf);
|
||||
@ -215,28 +228,9 @@ CProfileNode::CProfileNode( const char* _name, CProfileNode* _parent )
|
||||
{
|
||||
name = _name;
|
||||
recursion = 0;
|
||||
calls_total = 0;
|
||||
calls_frame_current = 0;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
int i;
|
||||
for( i = 0; i < PROFILE_AMORTIZE_FRAMES; i++ )
|
||||
{
|
||||
calls_frame_buffer[i] = 0;
|
||||
time_frame_buffer[i] = 0.0;
|
||||
}
|
||||
calls_frame_last = calls_frame_buffer;
|
||||
calls_frame_amortized = 0.0f;
|
||||
#else
|
||||
calls_frame_last = 0;
|
||||
#endif
|
||||
time_total = 0.0;
|
||||
time_frame_current = 0.0;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
time_frame_last = time_frame_buffer;
|
||||
time_frame_amortized = 0.0;
|
||||
#else
|
||||
time_frame_last = 0.0;
|
||||
#endif
|
||||
|
||||
Reset();
|
||||
|
||||
parent = _parent;
|
||||
|
||||
display_table = new CProfileNodeTable(this);
|
||||
@ -320,6 +314,7 @@ void CProfileNode::Reset()
|
||||
#else
|
||||
calls_frame_last = 0;
|
||||
#endif
|
||||
|
||||
time_total = 0.0;
|
||||
time_frame_current = 0.0;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
@ -329,6 +324,10 @@ void CProfileNode::Reset()
|
||||
time_frame_last = 0.0;
|
||||
#endif
|
||||
|
||||
mallocs_total = 0;
|
||||
mallocs_frame_current = 0;
|
||||
mallocs_frame_last = 0;
|
||||
|
||||
profile_iterator it;
|
||||
for( it = children.begin(); it != children.end(); it++ )
|
||||
(*it)->Reset();
|
||||
@ -340,6 +339,7 @@ void CProfileNode::Frame()
|
||||
{
|
||||
calls_total += calls_frame_current;
|
||||
time_total += time_frame_current;
|
||||
mallocs_total += mallocs_frame_current;
|
||||
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
calls_frame_amortized -= *calls_frame_last;
|
||||
@ -356,9 +356,11 @@ void CProfileNode::Frame()
|
||||
calls_frame_last = calls_frame_current;
|
||||
time_frame_last = time_frame_current;
|
||||
#endif
|
||||
mallocs_frame_last = mallocs_frame_current;
|
||||
|
||||
calls_frame_current = 0;
|
||||
time_frame_current = 0.0;
|
||||
mallocs_frame_current = 0;
|
||||
|
||||
profile_iterator it;
|
||||
for( it = children.begin(); it != children.end(); it++ )
|
||||
@ -367,11 +369,30 @@ void CProfileNode::Frame()
|
||||
(*it)->Frame();
|
||||
}
|
||||
|
||||
static long get_memory_alloc_count()
|
||||
{
|
||||
#if HAVE_VC_DEBUG_ALLOC
|
||||
static long bias = 0; // so we can subtract the allocations caused by this function
|
||||
void* p = malloc(1);
|
||||
long requestNumber = 0;
|
||||
int ok = _CrtIsMemoryBlock(p, 1, &requestNumber, NULL, NULL);
|
||||
UNUSED2(ok);
|
||||
free(p);
|
||||
++bias;
|
||||
return requestNumber - bias;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CProfileNode::Call()
|
||||
{
|
||||
calls_frame_current++;
|
||||
if( recursion++ == 0 )
|
||||
{
|
||||
start = get_time();
|
||||
start_mallocs = get_memory_alloc_count();
|
||||
}
|
||||
}
|
||||
|
||||
bool CProfileNode::Return()
|
||||
@ -379,7 +400,10 @@ bool CProfileNode::Return()
|
||||
if( !parent ) return( false );
|
||||
|
||||
if( ( --recursion == 0 ) && ( calls_frame_current != 0 ) )
|
||||
{
|
||||
time_frame_current += ( get_time() - start );
|
||||
mallocs_frame_current += ( get_memory_alloc_count() - start_mallocs );
|
||||
}
|
||||
return( recursion == 0 );
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <vector>
|
||||
#include "Singleton.h"
|
||||
#include "scripting/ScriptableObject.h"
|
||||
#include "lib/timer.h"
|
||||
|
||||
|
||||
#define PROFILE_AMORTIZE
|
||||
@ -29,6 +28,7 @@ class CProfileNode : public CJSObject<CProfileNode, true>
|
||||
friend class CProfileNodeTable;
|
||||
|
||||
const char* name;
|
||||
|
||||
int calls_total;
|
||||
int calls_frame_current;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
@ -38,6 +38,7 @@ class CProfileNode : public CJSObject<CProfileNode, true>
|
||||
#else
|
||||
int calls_frame_last;
|
||||
#endif
|
||||
|
||||
double time_total;
|
||||
double time_frame_current;
|
||||
#ifdef PROFILE_AMORTIZE
|
||||
@ -48,7 +49,12 @@ class CProfileNode : public CJSObject<CProfileNode, true>
|
||||
double time_frame_last;
|
||||
#endif
|
||||
|
||||
long mallocs_total;
|
||||
long mallocs_frame_current;
|
||||
long mallocs_frame_last;
|
||||
|
||||
double start;
|
||||
long start_mallocs;
|
||||
int recursion;
|
||||
|
||||
CProfileNode* parent;
|
||||
@ -74,6 +80,7 @@ public:
|
||||
int GetFrameCalls() const { return( calls_frame_last ); }
|
||||
double GetFrameTime() const { return( time_frame_last ); }
|
||||
#endif
|
||||
long GetFrameMallocs() const { return( mallocs_frame_last ); }
|
||||
|
||||
const CProfileNode* GetChild( const char* name ) const;
|
||||
const CProfileNode* GetScriptChild( const char* name ) const;
|
||||
|
@ -7,6 +7,17 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Avoid creating strings at runtime
|
||||
#define ACTION(n) \
|
||||
const char n##Name[] = "on" #n; \
|
||||
utf16string n##Name16(n##Name, n##Name + ARRAY_SIZE(n##Name)-1)
|
||||
ACTION(Enter);
|
||||
ACTION(Exit);
|
||||
ACTION(Tick);
|
||||
}
|
||||
|
||||
CAura::CAura( JSContext* cx, CEntity* source, CStrW& name, float radius, size_t tickRate, const CVector4D& color, JSObject* handler )
|
||||
: m_cx(cx), m_source(source), m_name(name), m_radius(radius), m_handler(handler),
|
||||
m_tickRate(tickRate), m_tickCyclePos(0), m_color(color)
|
||||
@ -27,6 +38,9 @@ void CAura::Update( size_t timestep )
|
||||
|
||||
std::vector<CEntity*> prevInfluenced, curInfluenced, entered, exited;
|
||||
|
||||
prevInfluenced.reserve(m_influenced.size());
|
||||
curInfluenced.reserve(m_influenced.size());
|
||||
|
||||
for( std::vector<HEntity>::iterator it = m_influenced.begin(); it != m_influenced.end(); it++ )
|
||||
{
|
||||
CEntity* ent = *it;
|
||||
@ -55,10 +69,8 @@ void CAura::Update( size_t timestep )
|
||||
jsval argv[1];
|
||||
|
||||
// Call onEnter on any new unit that has entered the aura
|
||||
CStrW enterName = L"onEnter";
|
||||
jsval enterFunction;
|
||||
utf16string enterName16 = enterName.utf16();
|
||||
if( JS_GetUCProperty( m_cx, m_handler, enterName16.c_str(), enterName16.length(), &enterFunction )
|
||||
if( JS_GetUCProperty( m_cx, m_handler, EnterName16.c_str(), EnterName16.length(), &enterFunction )
|
||||
&& enterFunction != JSVAL_VOID)
|
||||
{
|
||||
std::back_insert_iterator<std::vector<CEntity*> > ins( entered );
|
||||
@ -74,10 +86,8 @@ void CAura::Update( size_t timestep )
|
||||
}
|
||||
|
||||
// Call onExit on any unit that has exited the aura
|
||||
CStrW exitName = L"onExit";
|
||||
jsval exitFunction;
|
||||
utf16string exitName16 = exitName.utf16();
|
||||
if( JS_GetUCProperty( m_cx, m_handler, exitName16.c_str(), exitName16.length(), &exitFunction )
|
||||
if( JS_GetUCProperty( m_cx, m_handler, ExitName16.c_str(), ExitName16.length(), &exitFunction )
|
||||
&& exitFunction != JSVAL_VOID )
|
||||
{
|
||||
std::back_insert_iterator<std::vector<CEntity*> > ins( exited );
|
||||
@ -97,10 +107,8 @@ void CAura::Update( size_t timestep )
|
||||
if( m_tickRate > 0 && m_tickCyclePos > m_tickRate )
|
||||
{
|
||||
// It's time to tick; call OnTick on any unit that is in the aura
|
||||
CStrW tickName = L"onTick";
|
||||
jsval tickFunction;
|
||||
utf16string tickName16 = tickName.utf16();
|
||||
if( JS_GetUCProperty( m_cx, m_handler, tickName16.c_str(), tickName16.length(), &tickFunction )
|
||||
if( JS_GetUCProperty( m_cx, m_handler, TickName16.c_str(), TickName16.length(), &tickFunction )
|
||||
&& tickFunction != JSVAL_VOID )
|
||||
{
|
||||
for( std::vector<CEntity*>::iterator it = curInfluenced.begin(); it != curInfluenced.end(); it++ )
|
||||
@ -119,10 +127,8 @@ void CAura::RemoveAll()
|
||||
{
|
||||
jsval rval;
|
||||
jsval argv[1];
|
||||
CStrW exitName = L"onExit";
|
||||
jsval exitFunction;
|
||||
utf16string exitName16 = exitName.utf16();
|
||||
if( JS_GetUCProperty( m_cx, m_handler, exitName16.c_str(), exitName16.length(), &exitFunction )
|
||||
if( JS_GetUCProperty( m_cx, m_handler, ExitName16.c_str(), ExitName16.length(), &exitFunction )
|
||||
&& exitFunction != JSVAL_VOID )
|
||||
{
|
||||
// Call the exit function on everything in our influence
|
||||
@ -144,10 +150,8 @@ void CAura::Remove( CEntity* ent )
|
||||
{
|
||||
jsval rval;
|
||||
jsval argv[1];
|
||||
CStrW exitName = L"onExit";
|
||||
jsval exitFunction;
|
||||
utf16string exitName16 = exitName.utf16();
|
||||
if( JS_GetUCProperty( m_cx, m_handler, exitName16.c_str(), exitName16.length(), &exitFunction )
|
||||
if( JS_GetUCProperty( m_cx, m_handler, ExitName16.c_str(), ExitName16.length(), &exitFunction )
|
||||
&& exitFunction != JSVAL_VOID )
|
||||
{
|
||||
// Call the exit function on it
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "ps/Game.h"
|
||||
#include "maths/MathUtil.h"
|
||||
#include "Entity.h"
|
||||
#include "lib/timer.h"
|
||||
|
||||
int AURA_CIRCLE_POINTS;
|
||||
int SELECTION_CIRCLE_POINTS;
|
||||
|
Loading…
Reference in New Issue
Block a user