profiler hierarchy
This commit is contained in:
		| @@ -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) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user