22 #include "precompiled.h"
28 #if OS_WIN && !defined(NDEBUG)
29 # define USE_CRT_SET_ALLOC_HOOK
32 #if defined(__GLIBC__) && !defined(NDEBUG)
34 # define USE_GLIBC_MALLOC_OVERRIDE
61 virtual const std::vector<ProfileColumn>&
GetColumns();
143 if (row < nrchildren)
145 else if (row < nrchildren + nrscriptchildren)
147 else if (row > nrchildren + nrscriptchildren)
167 unlogged_time_frame -= (*it)->GetFrameTime();
168 unlogged_time_turn -= (*it)->GetTurnTime();
169 unlogged_mallocs_frame -= (*it)->GetFrameMallocs();
170 unlogged_mallocs_turn -= (*it)->GetTurnMallocs();
174 unlogged_time_frame -= (*it)->GetFrameTime();
175 unlogged_time_turn -= (*it)->GetTurnTime();
176 unlogged_mallocs_frame -= (*it)->GetFrameMallocs();
177 unlogged_mallocs_turn -= (*it)->GetTurnMallocs();
184 unlogged_time_turn = 0.0;
185 unlogged_mallocs_turn = 0.0;
235 if (row < nrchildren)
237 else if (row < nrchildren + nrscriptchildren)
254 return (row >= nrchildren && row < (nrchildren + nrscriptchildren));
288 if (collection.empty())
290 return std::accumulate(collection.begin(), collection.end(), 0.0) / collection.size();
327 if( (*it)->name == childName )
337 if( (*it)->name == childName )
347 if( (*it)->name == childName )
359 if( (*it)->name == childName )
431 #if defined(USE_CRT_SET_ALLOC_HOOK)
433 static long malloc_count = 0;
434 static _CRT_ALLOC_HOOK prev_hook;
436 static int crt_alloc_hook(
int allocType,
void* userData,
size_t size,
int blockType,
437 long requestNumber,
const unsigned char* filename,
int lineNumber)
443 return prev_hook(allocType, userData, size, blockType, requestNumber, filename, lineNumber);
450 prev_hook = _CrtSetAllocHook(crt_alloc_hook);
458 #elif defined(USE_GLIBC_MALLOC_HOOK)
462 static intptr_t malloc_count = 0;
463 static void *(*old_malloc_hook) (size_t,
const void*);
465 static void *malloc_hook(
size_t size,
const void*
UNUSED(caller))
476 __malloc_hook = old_malloc_hook;
477 void* result = malloc(size);
478 old_malloc_hook = __malloc_hook;
479 __malloc_hook = malloc_hook;
487 old_malloc_hook = __malloc_hook;
488 __malloc_hook = malloc_hook;
506 #elif defined(USE_GLIBC_MALLOC_OVERRIDE)
508 static intptr_t alloc_count = 0;
517 static bool alloc_bootstrapped =
false;
518 static char alloc_bootstrap_buffer[32];
519 static bool alloc_has_called_dlsym =
false;
524 void* malloc(
size_t sz)
528 static void *(*libc_malloc)(size_t);
529 if (libc_malloc == NULL)
531 alloc_has_called_dlsym =
true;
532 libc_malloc = (
void *(*)(size_t))
dlsym(RTLD_NEXT,
"malloc");
534 void* ret = libc_malloc(sz);
536 printf(
"### malloc(%d) = %p\n", sz, ret);
541 void* realloc(
void* ptr,
size_t sz)
545 static void *(*libc_realloc)(
void*, size_t);
546 if (libc_realloc == NULL)
548 alloc_has_called_dlsym =
true;
549 libc_realloc = (
void *(*)(
void*, size_t))
dlsym(RTLD_NEXT,
"realloc");
551 void* ret = libc_realloc(ptr, sz);
553 printf(
"### realloc(%p, %d) = %p\n", ptr, sz, ret);
558 void* calloc(
size_t nm,
size_t sz)
562 static void *(*libc_calloc)(size_t, size_t);
563 if (libc_calloc == NULL)
565 if (alloc_has_called_dlsym && !alloc_bootstrapped)
569 printf(
"### calloc-bs(%d, %d) = %p\n", nm, sz, alloc_bootstrap_buffer);
571 alloc_bootstrapped =
true;
572 return alloc_bootstrap_buffer;
574 alloc_has_called_dlsym =
true;
575 libc_calloc = (
void *(*)(size_t, size_t))
dlsym(RTLD_NEXT,
"calloc");
577 void* ret = libc_calloc(nm, sz);
579 printf(
"### calloc(%d, %d) = %p\n", nm, sz, ret);
586 static void (*libc_free)(
void*);
587 if (libc_free == NULL)
589 alloc_has_called_dlsym =
true;
590 libc_free = (void (*)(
void*))
dlsym(RTLD_NEXT,
"free");
595 printf(
"### free(%p)\n", ptr);
647 root(NULL), current(NULL), needs_structural_reset(false)
RingBuf< double, PROFILE_AMORTIZE_TURNS > time_per_turn
const CProfileNode * GetChild(const char *name) const
RingBuf< int, PROFILE_AMORTIZE_TURNS > calls_per_turn
static long get_memory_alloc_count()
static double average(const T &collection)
virtual CStr GetCellText(size_t row, size_t col)
GetCellText.
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
double GetFrameCalls() const
const char * GetName() const
CProfileNode * node
The node represented by this table.
static ColumnDescription columnDescription
Columns description (shared by all instances)
const std::vector< CProfileNode * > * GetScriptChildren() const
RingBuf< int, PROFILE_AMORTIZE_FRAMES > calls_per_frame
void StartScript(const char *name)
static void alloc_hook_initialize()
Class AbstractProfileTable: Profile table data model.
std::vector< CProfileNode * > children
long mallocs_turn_current
CProfileNode * GetParent() const
intptr_t cpu_AtomicAdd(volatile intptr_t *location, intptr_t increment)
add a signed value to a variable without the possibility of interference from other threads/CPUs...
Class CProfileNodeTable: Implement ProfileViewer's AbstractProfileTable interface in order to display...
int sprintf_s(char *buf, size_t max_chars, const char *fmt,...) PRINTF_ARGS(3)
CProfileNodeTable * display_table
friend class CProfileNodeTable
void push_back(const T &item)
virtual CStr GetTitle()
GetTitle: Longer, explanatory text (can be dynamic).
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
std::vector< CProfileNode * >::const_iterator const_profile_iterator
void PerformStructuralReset()
std::vector< ProfileColumn > columns
struct ColumnDescription: The only purpose of this helper structure is to provide the global construc...
virtual const std::vector< ProfileColumn > & GetColumns()
GetColumnDescriptions.
bool needs_structural_reset
#define ONCE(ONCE_code__)
execute the code passed as a parameter only the first time this is reached.
int pthread_mutex_lock(pthread_mutex_t *m)
void * dlsym(void *handle, const char *sym_name)
#define T(string_literal)
double GetFrameMallocs() const
const std::vector< CProfileNode * > * GetChildren() const
virtual AbstractProfileTable * GetChild(size_t row)
GetChild: Return a row's child table if the child is expandable.
long mallocs_frame_current
const CProfileNode * GetScriptChild(const char *name) const
virtual ~CProfileNodeTable()
double GetTurnTime() const
double time_frame_current
int pthread_mutex_unlock(pthread_mutex_t *m)
RingBuf< double, PROFILE_AMORTIZE_FRAMES > time_per_frame
CProfileNode(const char *name, CProfileNode *parent)
Struct ProfileColumn: Describes one column of an AbstractProfileTable.
double GetFrameTime() const
bool IsMainThread()
Returns whether the current thread is the 'main' thread (i.e.
RingBuf< long, PROFILE_AMORTIZE_FRAMES > mallocs_per_frame
RingBuf< long, PROFILE_AMORTIZE_TURNS > mallocs_per_turn
std::vector< CProfileNode * > script_children
double GetTurnMallocs() const
#define PTHREAD_MUTEX_INITIALIZER
std::vector< CProfileNode * >::iterator profile_iterator
virtual bool IsHighlightRow(size_t row)
IsHighlightRow.
CProfileNodeTable(CProfileNode *n)
double GetTurnCalls() const
virtual CStr GetName()
GetName: Short descriptive name of this table (should be static).
virtual size_t GetNumberRows()
GetNumberRows.
void Start(const char *name)