From 38354e19063478c8cda0408547ad05023b457041 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 28 Sep 2012 10:45:14 -0700
Subject: [PATCH] SH-3275 WIP Run viewer metrics for object update messages
 created separate constructor for static allocation of sampler buffer fixed
 start/stop/resume semantics of samplers and added sampler time interval
 tracking

---
 indra/llcommon/llcommon.cpp                |   1 +
 indra/llcommon/llqueuedthread.cpp          |   1 +
 indra/llcommon/llthread.cpp                |  14 ++-
 indra/llcommon/llthread.h                  |  10 +-
 indra/llcommon/lltrace.cpp                 | 117 +++++++++++++++++----
 indra/llcommon/lltrace.h                   | 108 ++++++++-----------
 indra/llimage/tests/llimageworker_test.cpp |   2 +
 indra/newview/llappviewer.cpp              |   2 +-
 8 files changed, 170 insertions(+), 85 deletions(-)

diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index c149a1fe5cc..c720df75550 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -29,6 +29,7 @@
 
 #include "llmemory.h"
 #include "llthread.h"
+#include "lltrace.h"
 
 //static
 BOOL LLCommon::sAprInitialized = FALSE;
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index a741d342d30..0a35474b7fd 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -28,6 +28,7 @@
 
 #include "llstl.h"
 #include "lltimer.h"	// ms_sleep()
+#include "lltrace.h"
 
 //============================================================================
 
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 2ff524d9bab..73848426271 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -32,6 +32,7 @@
 #include "llmutex.h"
 
 #include "lltimer.h"
+#include "lltrace.h"
 
 #if LL_LINUX || LL_SOLARIS
 #include <sched.h>
@@ -85,7 +86,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	sTraceData = new LLTrace::SlaveThreadTrace();
+	setTraceData(new LLTrace::SlaveThreadTrace());
 
 #if !LL_DARWIN
 	sThreadIndex = threadp->mID;
@@ -100,6 +101,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	threadp->mStatus = STOPPED;
 
 	delete sTraceData.get();
+	sTraceData = NULL;
 
 	return NULL;
 }
@@ -311,3 +313,13 @@ void LLThread::wakeLocked()
 		mRunCondition->signal();
 	}
 }
+
+LLTrace::ThreadTrace* LLThread::getTraceData()
+{
+	return sTraceData.get();
+}
+
+void LLThread::setTraceData( LLTrace::ThreadTrace* data )
+{
+	sTraceData = data;
+}
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 5cd287ec39f..334ea2f0da6 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -30,8 +30,12 @@
 #include "llapp.h"
 #include "llapr.h"
 #include "apr_thread_cond.h"
-#include "lltrace.h"
+#include "llmutex.h"
 
+namespace LLTrace
+{
+	class ThreadTrace;
+}
 class LL_COMMON_API LLThread
 {
 private:
@@ -87,8 +91,8 @@ class LL_COMMON_API LLThread
 
 	U32 getID() const { return mID; }
 
-	static LLTrace::ThreadTrace* getTraceData() { return sTraceData.get(); }
-	static void setTraceData(LLTrace::ThreadTrace* data) { sTraceData = data;}
+	static LLTrace::ThreadTrace* getTraceData();
+	static void setTraceData(LLTrace::ThreadTrace* data);
 
 private:
 	BOOL				mPaused;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 24a2b33a5f1..2da4363b1d0 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -55,40 +55,97 @@ MasterThreadTrace& getMasterThreadTrace()
 	return *gMasterThreadTrace;
 }
 
-
-
 ///////////////////////////////////////////////////////////////////////
 // Sampler
 ///////////////////////////////////////////////////////////////////////
 
+Sampler::Sampler(ThreadTrace* thread_trace) 
+:	mElapsedSeconds(0),
+	mIsStarted(false),
+	mThreadTrace(thread_trace)
+{
+}
 
-void Sampler::stop()
+Sampler::~Sampler()
 {
-	getThreadTrace()->deactivate(this);
+}
+
+void Sampler::start()
+{
+	reset();
+	resume();
+}
+
+void Sampler::reset()
+{
+	mF32Stats.reset();
+	mS32Stats.reset();
+	mStackTimers.reset();
+
+	mElapsedSeconds = 0.0;
+	mSamplingTimer.reset();
 }
 
 void Sampler::resume()
 {
-	getThreadTrace()->activate(this);
+	if (!mIsStarted)
+	{
+		mSamplingTimer.reset();
+		getThreadTrace()->activate(this);
+		mIsStarted = true;
+	}
+}
+
+void Sampler::stop()
+{
+	if (mIsStarted)
+	{
+		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+		getThreadTrace()->deactivate(this);
+		mIsStarted = false;
+	}
+}
+
+ThreadTrace* Sampler::getThreadTrace()
+{
+	return mThreadTrace;
+}
+
+void Sampler::makePrimary()
+{
+	mF32Stats.makePrimary();
+	mS32Stats.makePrimary();
+	mStackTimers.makePrimary();
 }
 
-class ThreadTrace* Sampler::getThreadTrace()
+void Sampler::mergeFrom( const Sampler* other )
 {
-	return LLThread::getTraceData();
+	mF32Stats.mergeFrom(other->mF32Stats);
+	mS32Stats.mergeFrom(other->mS32Stats);
+	mStackTimers.mergeFrom(other->mStackTimers);
 }
 
+
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
 
 ThreadTrace::ThreadTrace()
 {
-	mPrimarySampler.makePrimary();
+	mPrimarySampler = createSampler();
+	mPrimarySampler->makePrimary();
+	mPrimarySampler->start();
 }
 
-ThreadTrace::ThreadTrace( const ThreadTrace& other ) :	mPrimarySampler(other.mPrimarySampler)
+ThreadTrace::ThreadTrace( const ThreadTrace& other ) 
+:	mPrimarySampler(new Sampler(*(other.mPrimarySampler)))
 {
-	mPrimarySampler.makePrimary();
+	mPrimarySampler->makePrimary();
+}
+
+ThreadTrace::~ThreadTrace()
+{
+	delete mPrimarySampler;
 }
 
 void ThreadTrace::activate( Sampler* sampler )
@@ -117,11 +174,13 @@ void ThreadTrace::flushPrimary()
 	{
 		(*it)->mergeFrom(mPrimarySampler);
 	}
-	mPrimarySampler.reset();
+	mPrimarySampler->reset();
 }
 
-
-
+Sampler* ThreadTrace::createSampler()
+{
+	return new Sampler(this);
+}
 
 
 
@@ -129,12 +188,23 @@ void ThreadTrace::flushPrimary()
 // SlaveThreadTrace
 ///////////////////////////////////////////////////////////////////////
 
+SlaveThreadTrace::SlaveThreadTrace()
+:	ThreadTrace(getMasterThreadTrace()),
+	mSharedData(createSampler())
+{
+	getMasterThreadTrace().addSlaveThread(this);
+}
+
+SlaveThreadTrace::~SlaveThreadTrace()
+{
+	getMasterThreadTrace().removeSlaveThread(this);
+}
+
 void SlaveThreadTrace::pushToMaster()
 {
 	mSharedData.copyFrom(mPrimarySampler);
 }
 
-
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
@@ -155,7 +225,7 @@ void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	mSlaveThreadTraces.push_back(SlaveThreadTraceProxy(child));
+	mSlaveThreadTraces.push_back(SlaveThreadTraceProxy(child, createSampler()));
 }
 
 void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
@@ -175,15 +245,26 @@ void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
 }
 
 void MasterThreadTrace::pushToMaster()
-{
-
-}
+{}
 
 MasterThreadTrace::MasterThreadTrace()
 {
 	LLThread::setTraceData(this);
 }
 
+///////////////////////////////////////////////////////////////////////
+// MasterThreadTrace::SlaveThreadTraceProxy
+///////////////////////////////////////////////////////////////////////
+
+MasterThreadTrace::SlaveThreadTraceProxy::SlaveThreadTraceProxy( class SlaveThreadTrace* trace, Sampler* storage ) 
+:	mSlaveTrace(trace),
+	mSamplerStorage(storage)
+{}
 
+MasterThreadTrace::SlaveThreadTraceProxy::~SlaveThreadTraceProxy()
+{
+	delete mSamplerStorage;
 }
 
+
+}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 601b5ed182f..a443735e698 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -32,6 +32,7 @@
 
 #include "llmutex.h"
 #include "llmemory.h"
+#include "lltimer.h"
 
 #include <list>
 
@@ -39,6 +40,7 @@
 #define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
 #define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
 
+
 namespace LLTrace
 {
 	void init();
@@ -135,7 +137,7 @@ namespace LLTrace
 
 		static AccumulatorBuffer<ACCUMULATOR>& getDefaultBuffer()
 		{
-			static AccumulatorBuffer sBuffer;
+			static AccumulatorBuffer sBuffer(STATIC_ALLOC);
 			return sBuffer;
 		}
 
@@ -354,54 +356,38 @@ namespace LLTrace
 	class Sampler
 	{
 	public:
-		Sampler() {}
-		Sampler(const Sampler& other)
-		:	mF32Stats(other.mF32Stats),
-			mS32Stats(other.mS32Stats),
-			mTimers(other.mTimers)
-		{}
-
-		~Sampler()
-		{}
+		~Sampler();
 
-		void makePrimary()
-		{
-			mF32Stats.makePrimary();
-			mS32Stats.makePrimary();
-			mTimers.makePrimary();
-		}
-
-		void start()
-		{
-			reset();
-			resume();
-		}
+		void makePrimary();
 
+		void start();
 		void stop();
 		void resume();
 
-		void mergeFrom(const Sampler& other)
-		{
-			mF32Stats.mergeFrom(other.mF32Stats);
-			mS32Stats.mergeFrom(other.mS32Stats);
-			mTimers.mergeFrom(other.mTimers);
-		}
+		void mergeFrom(const Sampler* other);
 
-		void reset()
-		{
-			mF32Stats.reset();
-			mS32Stats.reset();
-			mTimers.reset();
-		}
+		void reset();
+
+		bool isStarted() { return mIsStarted; }
 
 	private:
+		friend class ThreadTrace;
+		Sampler(class ThreadTrace* thread_trace);
+
+		// no copy
+		Sampler(const Sampler& other) {}
 		// returns data for current thread
 		class ThreadTrace* getThreadTrace(); 
 
 		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
 		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
 
-		AccumulatorBuffer<TimerAccumulator>			mTimers;
+		AccumulatorBuffer<TimerAccumulator>			mStackTimers;
+
+		bool										mIsStarted;
+		LLTimer										mSamplingTimer;
+		F64											mElapsedSeconds;
+		ThreadTrace*								mThreadTrace;
 	};
 
 	class ThreadTrace
@@ -410,17 +396,19 @@ namespace LLTrace
 		ThreadTrace();
 		ThreadTrace(const ThreadTrace& other);
 
-		virtual ~ThreadTrace() {}
+		virtual ~ThreadTrace();
 
 		void activate(Sampler* sampler);
 		void deactivate(Sampler* sampler);
 		void flushPrimary();
 
+		Sampler* createSampler();
+
 		virtual void pushToMaster() = 0;
 
-		Sampler* getPrimarySampler() { return &mPrimarySampler; }
+		Sampler* getPrimarySampler() { return mPrimarySampler; }
 	protected:
-		Sampler					mPrimarySampler;
+		Sampler*				mPrimarySampler;
 		std::list<Sampler*>		mActiveSamplers;
 	};
 
@@ -440,11 +428,11 @@ namespace LLTrace
 	private:
 		struct SlaveThreadTraceProxy
 		{
-			SlaveThreadTraceProxy(class SlaveThreadTrace* trace)
-				:	mSlaveTrace(trace)
-			{}
+			SlaveThreadTraceProxy(class SlaveThreadTrace* trace, Sampler* storage);
+
+			~SlaveThreadTraceProxy();
 			class SlaveThreadTrace*	mSlaveTrace;
-			Sampler				mSamplerStorage;
+			Sampler*				mSamplerStorage;
 		};
 		typedef std::list<SlaveThreadTraceProxy> slave_thread_trace_list_t;
 
@@ -455,18 +443,8 @@ namespace LLTrace
 	class SlaveThreadTrace : public ThreadTrace
 	{
 	public:
-		explicit 
-		SlaveThreadTrace()
-		:	ThreadTrace(getMasterThreadTrace()),
-			mSharedData(mPrimarySampler)
-		{
-			getMasterThreadTrace().addSlaveThread(this);
-		}
-
-		~SlaveThreadTrace()
-		{
-			getMasterThreadTrace().removeSlaveThread(this);
-		}
+		SlaveThreadTrace();
+		~SlaveThreadTrace();
 
 		// call this periodically to gather stats data for master thread to consume
 		/*virtual*/ void pushToMaster();
@@ -479,29 +457,35 @@ namespace LLTrace
 		{
 		public:
 			explicit 
-			SharedData(const Sampler& other_sampler) 
-			:	mSampler(other_sampler)
-			{}
+			SharedData(Sampler* sampler) 
+			:	mSampler(sampler)
+			{
+			}
+
+			~SharedData()
+			{
+				delete mSampler;
+			}
 
-			void copyFrom(Sampler& source)
+			void copyFrom(Sampler* source)
 			{
 				LLMutexLock lock(&mSamplerMutex);
 				{	
-					mSampler.mergeFrom(source);
+					mSampler->mergeFrom(source);
 				}
 			}
 
-			void copyTo(Sampler& sink)
+			void copyTo(Sampler* sink)
 			{
 				LLMutexLock lock(&mSamplerMutex);
 				{
-					sink.mergeFrom(mSampler);
+					sink->mergeFrom(mSampler);
 				}
 			}
 		private:
 			// add a cache line's worth of unused space to avoid any potential of false sharing
 			LLMutex					mSamplerMutex;
-			Sampler					mSampler;
+			Sampler*				mSampler;
 		};
 		SharedData					mSharedData;
 	};
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index be7aae4eb7d..29497257ac7 100644
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -31,6 +31,8 @@
 #include "../llimageworker.h"
 // For timer class
 #include "../llcommon/lltimer.h"
+// for lltrace class
+#include "../llcommon/lltrace.h"
 // Tut header
 #include "../test/lltut.h"
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index fcbef491fef..0bb87dfa6ca 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -60,7 +60,7 @@
 #include "llcurl.h"
 #include "llcalc.h"
 #include "lltexturestats.h"
-#include "lltexturestats.h"
+#include "lltrace.h"
 #include "llviewerwindow.h"
 #include "llviewerdisplay.h"
 #include "llviewermedia.h"
-- 
GitLab