1
0
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:
Ykkrosh 2007-01-21 03:33:52 +00:00
parent ff52db91fa
commit 5c8250ddb8
5 changed files with 81 additions and 44 deletions

View File

@ -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"

View File

@ -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
@ -328,7 +323,11 @@ void CProfileNode::Reset()
#else
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 );
}

View File

@ -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;

View File

@ -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

View File

@ -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;