profiler hierarchy

This commit is contained in:
Irlan 2019-03-31 10:20:17 -03:00
parent f446f90266
commit 701e4c5b15
2 changed files with 88 additions and 37 deletions

View File

@ -21,36 +21,62 @@
Profiler* g_profiler = nullptr; Profiler* g_profiler = nullptr;
ProfilerListener* g_profilerListener = nullptr; ProfilerListener* g_profilerListener = nullptr;
Profiler::Profiler() Profiler::Profiler() : m_pool(sizeof(ProfilerNode))
{ {
m_root = nullptr;
m_top = nullptr; m_top = nullptr;
} }
Profiler::~Profiler() Profiler::~Profiler()
{ {
B3_ASSERT(m_root == nullptr);
B3_ASSERT(m_top == nullptr);
}
ProfilerNode* Profiler::CreateNode()
{
void* block = m_pool.Allocate();
ProfilerNode* n = new (block) ProfilerNode();
return n;
}
void Profiler::DestroyNode(ProfilerNode* node)
{
node->~ProfilerNode();
m_pool.Free(node);
} }
void Profiler::PushEvent(const char* name) void Profiler::PushEvent(const char* name)
{ {
m_time.Update(); m_time.Update();
ProfilerEvent e; ProfilerNode* n = CreateNode();
e.t0 = m_time.GetCurrentMilis(); n->name = name;
e.t1 = -1.0; n->t0 = m_time.GetCurrentMilis();
e.name = name; n->t1 = 0.0;
e.parent = m_top; n->parent = m_top;
m_events.PushBack(e); if (m_root == nullptr)
{
m_root = n;
m_top = n;
return;
}
m_top = &m_events.Back(); if (m_top)
{
m_top->children.PushBack(n);
}
m_top = n;
} }
void Profiler::PopEvent() void Profiler::PopEvent()
{ {
m_time.Update(); m_time.Update();
B3_ASSERT(m_top != nullptr);
m_top->t1 = m_time.GetCurrentMilis(); m_top->t1 = m_time.GetCurrentMilis();
B3_ASSERT(m_top->t1 > m_top->t0); B3_ASSERT(m_top->t1 > m_top->t0);
m_top = m_top->parent; m_top = m_top->parent;
@ -59,12 +85,41 @@ void Profiler::PopEvent()
void Profiler::Begin() void Profiler::Begin()
{ {
// If this assert is hit then it means Profiler::End hasn't been called. // If this assert is hit then it means Profiler::End hasn't been called.
B3_ASSERT(m_events.IsEmpty()); B3_ASSERT(m_root == nullptr);
B3_ASSERT(m_top == NULL); B3_ASSERT(m_top == nullptr);
}
static inline void RecurseEvents(ProfilerNode* node)
{
ProfilerListener* listener = g_profilerListener;
if (listener)
{
listener->BeginEvent(node->name, node->t0);
listener->EndEvent(node->name, node->t1);
}
for (u32 i = 0; i < node->children.Count(); ++i)
{
RecurseEvents(node->children[i]);
}
}
void Profiler::RecurseDestroy(ProfilerNode* node)
{
for (u32 i = 0; i < node->children.Count(); ++i)
{
RecurseDestroy(node->children[i]);
}
DestroyNode(node);
} }
void Profiler::End() void Profiler::End()
{ {
B3_ASSERT(m_top == nullptr);
ProfilerListener* listener = g_profilerListener; ProfilerListener* listener = g_profilerListener;
if (listener) if (listener)
@ -72,22 +127,12 @@ void Profiler::End()
listener->BeginEvents(); listener->BeginEvents();
} }
for (u32 i = 0; i < m_events.Count(); ++i) RecurseEvents(m_root);
{
ProfilerEvent e = m_events[i];
if (listener) RecurseDestroy(m_root);
{ m_root = nullptr;
listener->BeginEvent(e.name, e.t0);
listener->EndEvent(e.name, e.t1); B3_ASSERT(m_root == nullptr);
}
}
m_events.Resize(0);
B3_ASSERT(m_events.IsEmpty());
B3_ASSERT(m_top == NULL);
if (listener) if (listener)
{ {

View File

@ -20,21 +20,23 @@
#define PROFILER_H #define PROFILER_H
#include <bounce/common/math/math.h> #include <bounce/common/math/math.h>
#include <bounce/common/time.h> #include <bounce/common/memory/block_pool.h>
#include <bounce/common/template/array.h> #include <bounce/common/template/array.h>
#include <bounce/common/time.h>
class ProfilerListener; class ProfilerListener;
// A time-stamped profiler event. // Profiler node
struct ProfilerEvent struct ProfilerNode
{ {
const char* name; const char* name;
float64 t0; float64 t0;
float64 t1; float64 t1;
ProfilerEvent* parent; ProfilerNode* parent;
b3StackArray<ProfilerNode*, 256> children;
}; };
// A single-threaded event-based profiler. // A single-threaded profiler.
class Profiler class Profiler
{ {
public: public:
@ -51,17 +53,21 @@ public:
// This function also flushes the profiler. // This function also flushes the profiler.
void End(); void End();
// Add a profiler event to the queue. // Push an event.
// You can control the maximum number of profiler events using
// MAX_PROFILER_EVENTS.
void PushEvent(const char* name); void PushEvent(const char* name);
// Remove the top profiler event. // Remove the top profiler event.
void PopEvent(); void PopEvent();
private: private:
b3Time m_time; ProfilerNode* CreateNode();
b3StackArray<ProfilerEvent, 256> m_events; void DestroyNode(ProfilerNode* node);
ProfilerEvent* m_top;
void RecurseDestroy(ProfilerNode* node);
b3BlockPool m_pool; // pool of nodes
b3Time m_time; // timer
ProfilerNode* m_root; // tree root node
ProfilerNode* m_top; // top node
}; };
extern Profiler* g_profiler; extern Profiler* g_profiler;