Browse Source

Add more code to the tracer

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
7804f8a830
4 changed files with 107 additions and 24 deletions
  1. 1 1
      src/anki/util/CMakeLists.txt
  2. 1 1
      src/anki/util/ObjectAllocator.h
  3. 66 0
      src/anki/util/Trace.cpp
  4. 39 22
      src/anki/util/Trace.h

+ 1 - 1
src/anki/util/CMakeLists.txt

@@ -1,4 +1,4 @@
-set(SOURCES Assert.cpp Functions.cpp File.cpp Filesystem.cpp Memory.cpp System.cpp HighRezTimer.cpp ThreadPool.cpp ThreadHive.cpp Hash.cpp Logger.cpp String.cpp StringList.cpp)
+set(SOURCES Assert.cpp Functions.cpp File.cpp Filesystem.cpp Memory.cpp System.cpp HighRezTimer.cpp ThreadPool.cpp ThreadHive.cpp Hash.cpp Logger.cpp String.cpp StringList.cpp Trace.cpp)
 
 if(LINUX OR ANDROID OR MACOS)
 	set(SOURCES ${SOURCES} HighRezTimerPosix.cpp FilesystemPosix.cpp ThreadPosix.cpp)

+ 1 - 1
src/anki/util/ObjectAllocator.h

@@ -10,7 +10,7 @@
 namespace anki
 {
 
-/// @addtogroup util
+/// @addtogroup util_containers
 /// @{
 
 /// A simple allocator for objects of similar types.

+ 66 - 0
src/anki/util/Trace.cpp

@@ -0,0 +1,66 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/util/Trace.h>
+#include <anki/util/HighRezTimer.h>
+
+namespace anki
+{
+
+thread_local Tracer::ThreadLocal Tracer::m_threadLocal;
+
+Tracer::ThreadLocal& Tracer::getThreadLocal()
+{
+	ThreadLocal& out = m_threadLocal;
+	if(ANKI_UNLIKELY(!out.m_tracerKnowsAboutThis))
+	{
+		LockGuard<Mutex> lock(m_threadLocalMtx);
+		m_allThreadLocal.emplaceBack(m_alloc, &out);
+		out.m_tracerKnowsAboutThis = true;
+	}
+
+	return out;
+}
+
+void Tracer::beginEvent()
+{
+	if(m_enabled)
+	{
+		ThreadLocal& threadLocal = getThreadLocal();
+		Event* event = threadLocal.m_eventAlloc.newInstance(m_alloc);
+		event->m_timestamp = HighRezTimer::getCurrentTime();
+		threadLocal.m_events.pushBack(event);
+	}
+}
+
+void Tracer::endEvent(const char* eventName)
+{
+	if(m_enabled)
+	{
+		// Set the time in the event
+		ThreadLocal& threadLocal = getThreadLocal();
+		ANKI_ASSERT(!threadLocal.m_events.isEmpty());
+		Event& event = threadLocal.m_events.getBack();
+		event.m_name = eventName;
+		event.m_timestamp = HighRezTimer::getCurrentTime() - event.m_timestamp;
+
+		// Store a counter as well
+		increaseCounter(eventName, U64(event.m_duration * 1000000000.0));
+	}
+}
+
+void Tracer::increaseCounter(const char* counterName, U64 value)
+{
+	if(m_enabled)
+	{
+		ThreadLocal& threadLocal = getThreadLocal();
+		Counter* counter = threadLocal.m_counterAlloc.newInstance(m_alloc);
+		counter->m_name = counterName;
+		counter->m_value = value;
+		counter->m_frame = m_frame.load();
+	}
+}
+
+} // end namespace anki

+ 39 - 22
src/anki/util/Trace.h

@@ -6,6 +6,8 @@
 #pragma once
 
 #include <anki/util/File.h>
+#include <anki/util/List.h>
+#include <anki/util/ObjectAllocator.h>
 
 namespace anki
 {
@@ -21,23 +23,25 @@ public:
 
 	~Tracer();
 
-	ANKI_USE_RESULT Error init(GenericMemoryPoolAllocator<U8> alloc, const CString& cacheDir);
-
-	void registerEvent(const char* name);
-
-	void registerCounter(const char* name);
-
-	void startEvent();
+	void init(GenericMemoryPoolAllocator<U8> alloc)
+	{
+		m_alloc = alloc;
+	}
 
-	void stopEvent(U64 hash);
+	/// Begin a new event.
+	void beginEvent();
 
-	void increaseCounter(const char* eventName, U64 hash, U64 value);
+	/// End the event that got started with beginEvent().
+	void endEvent(const char* eventName);
 
-	/// Call it to begin the frame.
-	void beginFrame();
+	/// Increase a counter.
+	void increaseCounter(const char* counterName, U64 value);
 
 	/// Call it to end the frame.
-	void endFrame();
+	void endFrame()
+	{
+		m_frame.fetchAdd(1);
+	}
 
 	Bool getEnabled() const
 	{
@@ -49,6 +53,9 @@ public:
 		m_enabled = enable;
 	}
 
+	/// Flush all results to a file. Don't call that more than once.
+	ANKI_USE_RESULT Error flush(CString filename);
+
 private:
 	GenericMemoryPoolAllocator<U8> m_alloc;
 
@@ -57,33 +64,43 @@ private:
 	File m_traceFile;
 	File m_counterFile;
 
-	struct Event
+	/// Event.
+	class Event : public IntrusiveListEnabled<Event>
 	{
+	public:
 		const char* m_name;
 		Second m_timestamp;
 		Second m_duration;
-		ThreadId m_tid;
 	};
 
-	struct Counter
+	/// Counter.
+	class Counter : public IntrusiveListEnabled<Counter>
 	{
+	public:
 		const char* m_name;
-		U64 m_hash;
 		U64 m_value;
+		U64 m_frame;
 	};
 
-	class PerThread
+	class ThreadLocal
 	{
 	public:
 		ThreadId m_tid;
-		DynamicArray<Event> m_events;
-		DynamicArray<Counter> m_counters;
+		ObjectAllocatorSameType<Event> m_eventAlloc;
+		ObjectAllocatorSameType<Counter> m_counterAlloc;
+		IntrusiveList<Event> m_events;
+		IntrusiveList<Counter> m_counters;
+		Bool m_tracerKnowsAboutThis = false;
 	};
 
-	static thread_local PerThread* m_perThread;
+	static thread_local ThreadLocal m_threadLocal;
+	DynamicArray<ThreadLocal*> m_allThreadLocal; ///< The Tracer should know about all the ThreadLocal.
+	Mutex m_threadLocalMtx;
+
+	Atomic<U64> m_frame = {0};
 
-	DynamicArray<PerThread> m_perThread;
-	Mutex m_perThreadMtx;
+	/// Get the thread local ThreadLocal structure.
+	ThreadLocal& getThreadLocal();
 };
 /// @}