1
0
forked from 0ad/0ad

Profiler: Added malloc-counting to GCC. Fixed counting of unlogged allocations in the root node.

GUI: Tried a tiny bit to improve the response to mouse movement.
Atlas: Realised you can do "new XML(...)" to parse XML.

This was SVN commit r5180.
This commit is contained in:
Ykkrosh 2007-06-15 17:03:26 +00:00
parent 016f0fcba4
commit 5664f097d9
7 changed files with 79 additions and 32 deletions

View File

@ -43,7 +43,7 @@ function loadXML(name)
// "<?xml ...?>" (which E4X doesn't like parsing)
file.close();
return eval(xml);
return new XML(xml);
}
function init() { /* dummy function to make the script reloader happy */ }

View File

@ -33,6 +33,7 @@ CGUI
#include "lib/bits.h"
// TODO Gee: Whatever include CRect/CPos/CSize
#include "ps/Overlay.h"
#include "ps/Profile.h"
#include "scripting/ScriptingHost.h"
#include "ps/Hotkey.h"
@ -62,6 +63,7 @@ JSClass GUIClass = {
//-------------------------------------------------------------------
InReaction gui_handler(const SDL_Event_* ev)
{
PROFILE(" GUI event handler ");
return g_GUI.HandleEvent(ev);
}
@ -120,6 +122,7 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
// TODO Gee: (2004-09-08) Big TODO, don't do the below if the SDL_Event is something like a keypress!
try
{
PROFILE( "mouse events" );
// TODO Gee: Optimizations needed!
// these two recursive function are quite overhead heavy.

View File

@ -228,7 +228,6 @@ bool __ParseString<CGUISpriteInstance>(const CStr& Value, CGUISpriteInstance &Ou
template <>
bool __ParseString<CGUIList>(const CStr& UNUSED(Value), CGUIList& UNUSED(Output))
{
//LOG(WARNING, LOG_CATEGORY, "Cannot set a 'list' from a string.");
return false;
}
@ -289,17 +288,18 @@ void CInternalCGUIAccessorBase::HandleMessage(IGUIObject *pObject, const SGUIMes
//--------------------------------------------------------------------
#include "ps/CLogger.h"
template <typename T>
PS_RESULT GUI<T>::GetSettingPointer(const IGUIObject *pObject, const CStr& Setting, T* &Value)
{
if (pObject == NULL)
return PS_OBJECT_FAIL;
if (!pObject->SettingExists(Setting))
std::map<CStr, SGUISetting>::const_iterator it = pObject->m_Settings.find(Setting);
if (it == pObject->m_Settings.end())
return PS_SETTING_FAIL;
if (!pObject->m_Settings.find(Setting)->second.m_pSetting)
if (it->second.m_pSetting == NULL)
return PS_FAIL;
#ifndef NDEBUG
@ -307,7 +307,7 @@ PS_RESULT GUI<T>::GetSettingPointer(const IGUIObject *pObject, const CStr& Setti
#endif
// Get value
Value = (T*)pObject->m_Settings.find(Setting)->second.m_pSetting;
Value = (T*)(it->second.m_pSetting);
return PS_OK;
}

View File

@ -280,7 +280,7 @@ private:
* @throws PS_RESULT Depends on what pFunc might throw. PS_RESULT is standard.
* Itself doesn't throw anything.
*/
static void RecurseObject(const int &RR, IGUIObject *pObject, void_Object_pFunction_argT pFunc, const T &Argument)
static void RecurseObject(const int RR, IGUIObject *pObject, void_Object_pFunction_argT pFunc, const T &Argument)
{
// TODO Gee: Don't run this for the base object.
if (CheckIfRestricted(RR, pObject))
@ -301,7 +301,7 @@ private:
*
* @see RecurseObject()
*/
static void RecurseObject(const int &RR, IGUIObject *pObject, void_Object_pFunction_argRefT pFunc, T &Argument)
static void RecurseObject(const int RR, IGUIObject *pObject, void_Object_pFunction_argRefT pFunc, T &Argument)
{
if (CheckIfRestricted(RR, pObject))
return;
@ -321,7 +321,7 @@ private:
*
* @see RecurseObject()
*/
static void RecurseObject(const int &RR, IGUIObject *pObject, void_Object_pFunction pFunc)
static void RecurseObject(const int RR, IGUIObject *pObject, void_Object_pFunction pFunc)
{
if (CheckIfRestricted(RR, pObject))
return;
@ -347,7 +347,7 @@ private:
* @param pObject Object
* @return true if restricted
*/
static bool CheckIfRestricted(const int &RR, IGUIObject *pObject)
static bool CheckIfRestricted(const int RR, IGUIObject *pObject)
{
if (RR & GUIRR_HIDDEN)
{

View File

@ -86,6 +86,7 @@ static InReaction MainInputHandler(const SDL_Event_* ev)
// dispatch all pending events to the various receivers.
static void PumpEvents()
{
PROFILE( "dispatch events" );
in_dispatch_recorded_events();
SDL_Event_ ev;

View File

@ -12,6 +12,12 @@
#include "ProfileViewer.h"
#include "lib/timer.h"
#if GCC_VERSION && !defined(NDEBUG)
# define GLIBC_MALLOC_HOOK
# include <malloc.h>
# include "ThreadUtil.h"
#endif
///////////////////////////////////////////////////////////////////////////////////////////////
// CProfileNodeTable
@ -366,29 +372,71 @@ void CProfileNode::Frame()
(*it)->Frame();
}
// TODO: these should probably only count allocations that occur in the thread being profiled
#if HAVE_VC_DEBUG_ALLOC
static long memory_alloc_bias = 0; // so we can subtract the allocations caused by this function
static long get_memory_alloc_count()
{
#if HAVE_VC_DEBUG_ALLOC
// TODO: it's probably better to use _CrtSetAllocHook to increment a
// user-visible counter. (I didn't know that existed when I wrote this.)
// Find the number of allocations that have ever occurred, by doing a dummy
// allocation and checking its request number
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;
cpu_AtomicAdd(&memory_alloc_bias, 1);
return requestNumber - memory_alloc_bias;
}
#elif defined(GLIBC_MALLOC_HOOK)
// Set up malloc hooks to count allocations - see
// http://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html
static int malloc_count = 0;
static void *(*old_malloc_hook) (size_t, const void*);
static CMutex malloc_mutex;
static void *malloc_hook(size_t size, const void* caller)
{
// TODO: this is totally not nicely thread-safe - glibc's hook system seems to
// not make threading easy, and I don't want to think too hard, so this is
// just all put inside a lock.
CScopeLock lock(malloc_mutex);
++malloc_count;
__malloc_hook = old_malloc_hook;
void* result = malloc(size);
old_malloc_hook = __malloc_hook;
__malloc_hook = malloc_hook;
return result;
}
static void malloc_initialize_hook()
{
CScopeLock lock(malloc_mutex);
old_malloc_hook = __malloc_hook;
__malloc_hook = malloc_hook;
}
/*
It would be nice to do:
__attribute__ ((visibility ("default"))) void (*__malloc_initialize_hook)() = malloc_initialize_hook;
except that doesn't seem to work in practice, since something (?) resets the
hook to NULL some time while loading the game, after we've set it here - so
we just call malloc_initialize_hook once inside CProfileManager::Frame instead
and hope nobody deletes our hook after that.
*/
static long get_memory_alloc_count()
{
return malloc_count;
}
#else
// TODO: support other compilers if it's easy.
static long get_memory_alloc_count()
{
// TODO: don't show this column of data when we don't have sensible values
// to display.
return 0;
#endif
}
#endif
void CProfileNode::Call()
{
@ -429,6 +477,7 @@ CProfileManager::CProfileManager()
root = new CProfileNode( "root", NULL );
current = root;
frame_start = 0.0;
frame_start_mallocs = 0;
g_ProfileViewer.AddRootTable(root->display_table);
}
@ -478,16 +527,22 @@ void CProfileManager::Stop()
void CProfileManager::Reset()
{
root->Reset();
start = get_time();
frame_start = get_time();
start = frame_start = get_time();
start_mallocs = frame_start_mallocs = get_memory_alloc_count();
}
void CProfileManager::Frame()
{
#ifdef GLIBC_MALLOC_HOOK
ONCE(malloc_initialize_hook());
#endif
root->time_frame_current = ( get_time() - frame_start );
root->mallocs_frame_current = ( get_memory_alloc_count() - frame_start_mallocs );
root->Frame();
frame_start = get_time();
frame_start_mallocs = get_memory_alloc_count();
}
void CProfileManager::StructuralReset()
@ -497,15 +552,3 @@ void CProfileManager::StructuralReset()
current = root;
g_ProfileViewer.AddRootTable(root->display_table);
}
double CProfileManager::GetTime()
{
return( get_time() - start );
}
double CProfileManager::GetFrameTime()
{
return( get_time() - frame_start );
}

View File

@ -112,6 +112,8 @@ class CProfileManager : public Singleton<CProfileManager>
CProfileNode* current;
double start;
double frame_start;
long start_mallocs;
long frame_start_mallocs;
std::map<CStr8, const char*> m_internedStrings;
public:
@ -136,8 +138,6 @@ public:
inline const CProfileNode* GetCurrent() { return( current ); }
inline const CProfileNode* GetRoot() { return( root ); }
double GetTime();
double GetFrameTime();
};
#define g_Profiler CProfileManager::GetSingleton()