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:
parent
016f0fcba4
commit
5664f097d9
@ -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 */ }
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user