From 701e4c5b15bb144cd79406bd32d2d96513b92323 Mon Sep 17 00:00:00 2001 From: Irlan Date: Sun, 31 Mar 2019 10:20:17 -0300 Subject: [PATCH] profiler hierarchy --- examples/testbed/framework/profiler.cpp | 97 ++++++++++++++++++------- examples/testbed/framework/profiler.h | 28 ++++--- 2 files changed, 88 insertions(+), 37 deletions(-) diff --git a/examples/testbed/framework/profiler.cpp b/examples/testbed/framework/profiler.cpp index 3678fe9..579c968 100644 --- a/examples/testbed/framework/profiler.cpp +++ b/examples/testbed/framework/profiler.cpp @@ -21,36 +21,62 @@ Profiler* g_profiler = nullptr; ProfilerListener* g_profilerListener = nullptr; -Profiler::Profiler() +Profiler::Profiler() : m_pool(sizeof(ProfilerNode)) { + m_root = nullptr; m_top = nullptr; } 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) { m_time.Update(); - ProfilerEvent e; - e.t0 = m_time.GetCurrentMilis(); - e.t1 = -1.0; - e.name = name; - e.parent = m_top; + ProfilerNode* n = CreateNode(); + n->name = name; + n->t0 = m_time.GetCurrentMilis(); + n->t1 = 0.0; + 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() { m_time.Update(); + B3_ASSERT(m_top != nullptr); m_top->t1 = m_time.GetCurrentMilis(); - B3_ASSERT(m_top->t1 > m_top->t0); m_top = m_top->parent; @@ -59,12 +85,41 @@ void Profiler::PopEvent() void Profiler::Begin() { // If this assert is hit then it means Profiler::End hasn't been called. - B3_ASSERT(m_events.IsEmpty()); - B3_ASSERT(m_top == NULL); + B3_ASSERT(m_root == nullptr); + 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() { + B3_ASSERT(m_top == nullptr); + ProfilerListener* listener = g_profilerListener; if (listener) @@ -72,22 +127,12 @@ void Profiler::End() listener->BeginEvents(); } - for (u32 i = 0; i < m_events.Count(); ++i) - { - ProfilerEvent e = m_events[i]; + RecurseEvents(m_root); + + RecurseDestroy(m_root); + m_root = nullptr; - if (listener) - { - listener->BeginEvent(e.name, e.t0); - - listener->EndEvent(e.name, e.t1); - } - } - - m_events.Resize(0); - - B3_ASSERT(m_events.IsEmpty()); - B3_ASSERT(m_top == NULL); + B3_ASSERT(m_root == nullptr); if (listener) { diff --git a/examples/testbed/framework/profiler.h b/examples/testbed/framework/profiler.h index e1f2225..3a463ed 100644 --- a/examples/testbed/framework/profiler.h +++ b/examples/testbed/framework/profiler.h @@ -20,21 +20,23 @@ #define PROFILER_H #include -#include +#include #include +#include class ProfilerListener; -// A time-stamped profiler event. -struct ProfilerEvent +// Profiler node +struct ProfilerNode { const char* name; float64 t0; float64 t1; - ProfilerEvent* parent; + ProfilerNode* parent; + b3StackArray children; }; -// A single-threaded event-based profiler. +// A single-threaded profiler. class Profiler { public: @@ -51,17 +53,21 @@ public: // This function also flushes the profiler. void End(); - // Add a profiler event to the queue. - // You can control the maximum number of profiler events using - // MAX_PROFILER_EVENTS. + // Push an event. void PushEvent(const char* name); // Remove the top profiler event. void PopEvent(); private: - b3Time m_time; - b3StackArray m_events; - ProfilerEvent* m_top; + ProfilerNode* CreateNode(); + void DestroyNode(ProfilerNode* node); + + 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;