From 04bdc8ba83c297945dd60489c241b88adf892ff4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 1 Jul 2013 17:04:01 -0700
Subject: [PATCH] SH-4294 FIX Interesting: Statistics Texture cache hit rate is
 always 0% also, removed LLTrace::init and cleanup removed derived class
 implementation of memory stat for LLMemTrackable is automatic now

---
 indra/llcommon/llcommon.cpp                   | 14 +++-
 indra/llcommon/llfasttimer.cpp                |  2 +-
 indra/llcommon/llthread.cpp                   |  2 +-
 indra/llcommon/lltrace.cpp                    | 26 +++----
 indra/llcommon/lltrace.h                      | 68 +++++++++++--------
 indra/llcommon/lltraceaccumulators.h          |  7 +-
 indra/llcommon/lltracethreadrecorder.cpp      | 14 ++--
 indra/llcommon/lltracethreadrecorder.h        | 10 ++-
 indra/llimage/llimage.cpp                     | 13 ++--
 indra/llimage/llimage.h                       |  2 -
 indra/llimage/tests/llimageworker_test.cpp    |  8 ---
 indra/llkdu/tests/llimagej2ckdu_test.cpp      |  2 -
 indra/llui/llstatbar.cpp                      | 12 ++--
 indra/llui/lltextbase.cpp                     |  2 -
 indra/llui/lltextbase.h                       |  2 -
 indra/llui/llview.cpp                         |  1 -
 indra/llui/llview.h                           |  1 -
 indra/llui/llviewmodel.cpp                    |  2 -
 indra/llui/llviewmodel.h                      |  2 -
 indra/newview/llappviewer.cpp                 |  2 +-
 indra/newview/lldrawable.cpp                  |  1 -
 indra/newview/lldrawable.h                    |  1 -
 indra/newview/llfasttimerview.cpp             | 10 +--
 indra/newview/llviewerobject.cpp              |  2 -
 indra/newview/llviewerobject.h                |  1 -
 indra/newview/llvocache.cpp                   |  2 -
 indra/newview/llvocache.h                     |  3 -
 .../newview/tests/llviewerassetstats_test.cpp |  6 +-
 indra/test/test.cpp                           |  9 ++-
 29 files changed, 107 insertions(+), 120 deletions(-)

diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index c720df75550..96ec0cdefef 100755
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -30,10 +30,13 @@
 #include "llmemory.h"
 #include "llthread.h"
 #include "lltrace.h"
+#include "lltracethreadrecorder.h"
 
 //static
 BOOL LLCommon::sAprInitialized = FALSE;
 
+static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
+
 //static
 void LLCommon::initClass()
 {
@@ -45,13 +48,20 @@ void LLCommon::initClass()
 	}
 	LLTimer::initClass();
 	LLThreadSafeRefCount::initThreadSafeRefCount();
-	LLTrace::init();
+
+	if (!sMasterThreadRecorder)
+	{
+		sMasterThreadRecorder = new LLTrace::ThreadRecorder();
+		LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
+	}
 }
 
 //static
 void LLCommon::cleanupClass()
 {
-	LLTrace::cleanup();
+	delete sMasterThreadRecorder;
+	sMasterThreadRecorder = NULL;
+	LLTrace::set_master_thread_recorder(NULL);
 	LLThreadSafeRefCount::cleanupThreadSafeRefCount();
 	LLTimer::cleanupClass();
 	if (sAprInitialized)
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 7a7f1c79c15..a72f16d3851 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -250,7 +250,7 @@ void TimeBlock::updateTimes()
 {
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimerStackRecord* stack_record	= LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
-	if (stack_record) return;
+	if (!stack_record) return;
 
 	U64 cur_time = getCPUClockCount64();
 	BlockTimer* cur_timer				= stack_record->mActiveTimer;
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index d07cccdf152..166a4eb26d2 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -93,7 +93,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	LLTrace::ThreadRecorder thread_recorder(LLTrace::getUIThreadRecorder());
+	LLTrace::ThreadRecorder thread_recorder(*LLTrace::get_master_thread_recorder());
 
 #if !LL_DARWIN
 	sThreadID = threadp->mID;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 26c19e5121f..3dffbe6d4a5 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -30,34 +30,26 @@
 #include "lltracethreadrecorder.h"
 #include "llfasttimer.h"
 
-static S32 sInitializationCount = 0;
-
 namespace LLTrace
 {
 
-void init()
+TraceBase::TraceBase( const char* name, const char* description ) 
+:	mName(name),
+	mDescription(description ? description : "")
 {
-	if (sInitializationCount++ == 0)
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	if (LLTrace::get_master_thread_recorder() != NULL)
 	{
-		gUIThreadRecorder = new ThreadRecorder();
+		llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
 	}
+#endif
 }
 
-bool isInitialized()
+const char* TraceBase::getUnitLabel()
 {
-	return sInitializationCount > 0; 
+	return "";
 }
 
-void cleanup()
-{
-	if (--sInitializationCount == 0)
-	{
-		delete gUIThreadRecorder;
-		gUIThreadRecorder = NULL;
-	}
-}
-
-
 TimeBlockTreeNode::TimeBlockTreeNode() 
 :	mBlock(NULL),
 	mParent(NULL),
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 72ef51c2322..1cde450dc25 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -53,19 +53,29 @@ STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.val
 template<typename UNIT_TYPE, typename STORAGE_TYPE> 
 STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
 
-void init();
-void cleanup();
-bool isInitialized();
+class TraceBase
+{
+public:
+	TraceBase(const char* name, const char* description);
+	virtual ~TraceBase() {};
+	virtual const char* getUnitLabel();
+
+	const std::string& getName() const { return mName; }
+
+protected:
+	const std::string	mName;
+	const std::string	mDescription;
+};
 
 template<typename ACCUMULATOR>
 class TraceType 
-:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
+:	public TraceBase,
+	public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 {
 public:
 	TraceType(const char* name, const char* description = NULL)
 	:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
-		mName(name),
-		mDescription(description ? description : ""),
+		TraceBase(name, description),
 		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
 	{}
 
@@ -78,13 +88,7 @@ class TraceType
 	size_t getIndex() const { return mAccumulatorIndex; }
 	static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
 
-	virtual const char* getUnitLabel() { return ""; }
-
-	const std::string& getName() const { return mName; }
-
-protected:
-	const std::string	mName;
-	const std::string	mDescription;
+private:
 	const size_t		mAccumulatorIndex;
 };
 
@@ -320,7 +324,7 @@ class MemTrackable
 	template<typename TRACKED, typename TRACKED_IS_TRACKER>
 	struct TrackMemImpl;
 
-	typedef MemTrackable<DERIVED> mem_trackable_t;
+	typedef MemTrackable<DERIVED, ALIGNMENT> mem_trackable_t;
 
 public:
 	typedef void mem_trackable_tag_t;
@@ -332,7 +336,7 @@ class MemTrackable
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
@@ -344,7 +348,7 @@ class MemTrackable
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
@@ -356,7 +360,7 @@ class MemTrackable
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
@@ -368,7 +372,7 @@ class MemTrackable
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
@@ -394,14 +398,16 @@ class MemTrackable
 	}
 
 
-	void memClaimAmount(size_t size)
+	template<typename AMOUNT_T>
+	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-		mMemFootprint += size;
+		MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+		mMemFootprint += (size_t)size;
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
 		}
+		return size;
 	}
 
 	// remove memory we had claimed from our calculated footprint
@@ -419,24 +425,28 @@ class MemTrackable
 		return value;
 	}
 
-	void memDisclaimAmount(size_t size)
+	template<typename AMOUNT_T>
+	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
 		}
+		return size;
 	}
 
 private:
 	size_t mMemFootprint;
+	static MemStatHandle sMemStat;
+
 
 	template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
 	struct TrackMemImpl
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -447,7 +457,7 @@ class MemTrackable
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -462,7 +472,7 @@ class MemTrackable
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked));
@@ -471,7 +481,7 @@ class MemTrackable
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked));
@@ -480,5 +490,9 @@ class MemTrackable
 	};
 };
 
+template<typename DERIVED, size_t ALIGNMENT>
+MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat(typeid(DERIVED).name());
+
+
 }
 #endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 825cc9e3a8e..fac6347ff91 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -33,6 +33,7 @@
 #include "llunit.h"
 #include "lltimer.h"
 #include "llrefcount.h"
+#include "llthreadlocalstorage.h"
 
 namespace LLTrace
 {
@@ -142,12 +143,6 @@ namespace LLTrace
 		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
 		size_t reserveSlot()
 		{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-			if (LLTrace::isInitialized())
-			{
-				llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
-			}
-#endif
 			size_t next_slot = sNextStorageSlot++;
 			if (next_slot >= mStorageSize)
 			{
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index e88c5bf177c..7ac0e751546 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -31,13 +31,14 @@
 namespace LLTrace
 {
 
-ThreadRecorder* gUIThreadRecorder = NULL;
+static ThreadRecorder* sMasterThreadRecorder = NULL;
 
 ///////////////////////////////////////////////////////////////////////
 // ThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
 ThreadRecorder::ThreadRecorder()
+:	mMasterRecorder(NULL)
 {
 	init();
 }
@@ -268,10 +269,15 @@ void ThreadRecorder::pullFromChildren()
 }
 
 
-ThreadRecorder& getUIThreadRecorder()
+void set_master_thread_recorder(ThreadRecorder* recorder)
 {
-	llassert(gUIThreadRecorder != NULL);
-	return *gUIThreadRecorder;
+	sMasterThreadRecorder = recorder;
+}
+
+
+ThreadRecorder* get_master_thread_recorder()
+{
+	return sMasterThreadRecorder;
 }
 
 LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index b5ed77416c1..535f8552008 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -92,13 +92,11 @@ namespace LLTrace
 
 	};
 
-	//FIXME: let user code set up thread recorder topology
-	extern ThreadRecorder* gUIThreadRecorder ;
-
-	const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
-	void set_thread_recorder(class ThreadRecorder*);
-	ThreadRecorder& getUIThreadRecorder();
+	const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder();
+	void set_thread_recorder(ThreadRecorder*);
 
+	void set_master_thread_recorder(ThreadRecorder*);
+	ThreadRecorder* get_master_thread_recorder();
 }
 
 #endif // LL_LLTRACETHREADRECORDER_H
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 50df2ebe55f..395e6a6cc50 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -50,7 +50,6 @@ LLMutex* LLImage::sMutex = NULL;
 bool LLImage::sUseNewByteRange = false;
 S32  LLImage::sMinimalReverseByteRangePercent = 75;
 LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ;
-LLTrace::MemStatHandle	LLImageBase::sMemStat("LLImage");
 
 //static
 void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent)
@@ -159,9 +158,8 @@ void LLImageBase::sanityCheck()
 void LLImageBase::deleteData()
 {
 	FREE_MEM(sPrivatePoolp, mData) ;
-	memDisclaimAmount(mDataSize);
+	memDisclaimAmount(mDataSize) = 0;
 	mData = NULL;
-	mDataSize = 0;
 }
 
 // virtual
@@ -225,9 +223,7 @@ U8* LLImageBase::reallocateData(S32 size)
 		FREE_MEM(sPrivatePoolp, mData) ;
 	}
 	mData = new_datap;
-	memDisclaimAmount(mDataSize);
-	mDataSize = size;
-	memClaimAmount(mDataSize);
+	memClaimAmount(memDisclaimAmount(mDataSize) = size);
 	return mData;
 }
 
@@ -1612,9 +1608,8 @@ static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8*
 void LLImageBase::setDataAndSize(U8 *data, S32 size)
 { 
 	ll_assert_aligned(data, 16);
-	memDisclaimAmount(mDataSize);
-	mData = data; mDataSize = size; 
-	memClaimAmount(mDataSize);
+	mData = data; 
+	memClaimAmount(memDisclaimAmount(mDataSize) = size); 
 }	
 
 //static
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 504b7e4795c..b2bfdba3f84 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -165,8 +165,6 @@ class LLImageBase
 	static void destroyPrivatePool() ;
 	static LLPrivateMemoryPool* getPrivatePool() {return sPrivatePoolp;}
 
-	static LLTrace::MemStatHandle sMemStat;
-
 private:
 	U8 *mData;
 	S32 mDataSize;
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index b6f2694742c..7d7e9e036e2 100755
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -44,9 +44,6 @@
 // * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
 // * A simulator for a class can be implemented here. Please comment and document thoroughly.
 
-LLTrace::MemStatHandle	LLImageBase::sMemStat("LLImage");
-
-
 LLImageBase::LLImageBase() 
 : mData(NULL),
 mDataSize(0),
@@ -115,17 +112,14 @@ namespace tut
 	{
 		// Instance to be tested
 		LLImageDecodeThread* mThread;
-
 		// Constructor and destructor of the test wrapper
 		imagedecodethread_test()
 		{
-			LLTrace::init();
 			mThread = NULL;
 		}
 		~imagedecodethread_test()
 		{
 			delete mThread;
-			LLTrace::cleanup();
 		}
 	};
 
@@ -143,7 +137,6 @@ namespace tut
 		imagerequest_test()
 		{
 			done = false;
-			LLTrace::init();
 
 			mRequest = new LLImageDecodeThread::ImageRequest(0, 0,
 											 LLQueuedThread::PRIORITY_NORMAL, 0, FALSE,
@@ -154,7 +147,6 @@ namespace tut
 			// We should delete the object *but*, because its destructor is protected, that cannot be
 			// done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine...
 			//delete mRequest;
-			LLTrace::cleanup();
 		}
 	};
 
diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp
index 14fbf344abf..0e73f33e047 100755
--- a/indra/llkdu/tests/llimagej2ckdu_test.cpp
+++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp
@@ -44,8 +44,6 @@
 // End Stubbing
 // -------------------------------------------------------------------------------------------
 // Stub the LL Image Classes
-LLTrace::MemStatHandle	LLImageBase::sMemStat("LLImage");
-
 LLImageRaw::LLImageRaw() { }
 LLImageRaw::~LLImageRaw() { }
 U8* LLImageRaw::allocateData(S32 ) { return NULL; }
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
index d3cc2733e66..fd88565de47 100755
--- a/indra/llui/llstatbar.cpp
+++ b/indra/llui/llstatbar.cpp
@@ -345,9 +345,9 @@ void LLStatBar::draw()
 					else if (mSampleFloatp)
 					{
 						//rate isn't defined for sample stats, so use mean
-						begin       = ((recording.getMean(*mEventFloatp)  - mMinBar) * value_scale);
-						end         = ((recording.getMean(*mEventFloatp)  - mMinBar) * value_scale) + 1;
-						num_samples = recording.getSampleCount(*mEventFloatp);
+						begin       = ((recording.getMean(*mSampleFloatp)  - mMinBar) * value_scale);
+						end         = ((recording.getMean(*mSampleFloatp)  - mMinBar) * value_scale) + 1;
+						num_samples = recording.getSampleCount(*mSampleFloatp);
 					}
 				}
 				else
@@ -366,9 +366,9 @@ void LLStatBar::draw()
 					}
 					else if (mSampleFloatp)
 					{
-						begin       = ((recording.getMean(*mEventFloatp)  - mMinBar) * value_scale);
-						end         = ((recording.getMean(*mEventFloatp)  - mMinBar) * value_scale) + 1;
-						num_samples = recording.getSampleCount(*mEventFloatp);
+						begin       = ((recording.getMean(*mSampleFloatp)  - mMinBar) * value_scale);
+						end         = ((recording.getMean(*mSampleFloatp)  - mMinBar) * value_scale) + 1;
+						num_samples = recording.getSampleCount(*mSampleFloatp);
 					}
  				}
 				
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 7243931dbbd..98459417780 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -48,8 +48,6 @@ const F32	CURSOR_FLASH_DELAY = 1.0f;  // in seconds
 const S32	CURSOR_THICKNESS = 2;
 const F32	TRIPLE_CLICK_INTERVAL = 0.3f;	// delay between double and triple click.
 
-LLTrace::MemStatHandle	LLTextSegment::sMemStat("LLTextSegment");
-
 LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num) 
 :	mDocIndexStart(index_start), 
 	mDocIndexEnd(index_end),
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 74dc7f96931..3e93b7de65b 100755
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -100,8 +100,6 @@ class LLTextSegment
 	S32						getEnd() const						{ return mEnd; }
 	void					setEnd( S32 end )					{ mEnd = end; }
 
-	static LLTrace::MemStatHandle sMemStat;
-
 protected:
 	S32				mStart;
 	S32				mEnd;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index daeb4d79399..b2805a32e85 100755
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -69,7 +69,6 @@ LLView* LLView::sPreviewClickedElement = NULL;
 BOOL	LLView::sDrawPreviewHighlights = FALSE;
 S32		LLView::sLastLeftXML = S32_MIN;
 S32		LLView::sLastBottomXML = S32_MIN;
-LLTrace::MemStatHandle	LLView::sMemStat("LLView");
 std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
 
 LLView::DrilldownFunc LLView::sDrilldown =
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 0568fa889a3..62bfb545664 100755
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -675,7 +675,6 @@ class LLView
 	static S32 sLastLeftXML;
 	static S32 sLastBottomXML;
 	static BOOL sForceReshape;
-	static LLTrace::MemStatHandle sMemStat;
 };
 
 namespace LLInitParam
diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp
index 901260bec85..dff0dcb2fd6 100755
--- a/indra/llui/llviewmodel.cpp
+++ b/indra/llui/llviewmodel.cpp
@@ -35,8 +35,6 @@
 // external library headers
 // other Linden headers
 
-LLTrace::MemStatHandle	LLViewModel::sMemStat("LLViewModel");
-
 ///
 LLViewModel::LLViewModel()
  : mDirty(false)
diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h
index 2c016d25606..a2ca20c739c 100755
--- a/indra/llui/llviewmodel.h
+++ b/indra/llui/llviewmodel.h
@@ -83,8 +83,6 @@ class LLViewModel
 	// 
     void setDirty() { mDirty = true; }
 
-	static LLTrace::MemStatHandle sMemStat;
-
 protected:
     LLSD mValue;
     bool mDirty;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 348eb43b5e8..e77f793a438 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1297,7 +1297,7 @@ bool LLAppViewer::mainLoop()
 		LLTrace::get_frame_recording().nextPeriod();
 		LLTrace::TimeBlock::logStats();
 
-		LLTrace::getUIThreadRecorder().pullFromChildren();
+		LLTrace::get_master_thread_recorder()->pullFromChildren();
 
 		//clear call stack records
 		llclearcallstacks;
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 628f7f7bfb1..3dddf4b5545 100755
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -59,7 +59,6 @@ const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f;
 static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
 
 extern bool gShiftFrame;
-LLTrace::MemStatHandle	LLDrawable::sMemStat("LLDrawable");
 
 
 ////////////////////////
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index b7c5aeb5a87..4558597d89b 100755
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -293,7 +293,6 @@ class LLDrawable
 	F32				mDistanceWRTCamera;
 
 	static F32 sCurPixelAngle; //current pixels per radian
-	static LLTrace::MemStatHandle sMemStat;
 
 private:
 	typedef std::vector<LLFace*> face_list_t;
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 7a5e1dcad07..d9226594351 100755
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -430,18 +430,18 @@ void LLFastTimerView::draw()
 					}
 
 void LLFastTimerView::onOpen(const LLSD& key)
-				{
+{
 	setPauseState(false);
 	mRecording.reset();
 	mRecording.appendPeriodicRecording(LLTrace::get_frame_recording());
 	for(std::deque<TimerBarRow>::iterator it = mTimerBarRows.begin(), end_it = mTimerBarRows.end();
 		it != end_it; 
-				++it)
-			{
+		++it)
+	{
 		delete []it->mBars;
 		it->mBars = NULL;
-					}
-					}
+	}
+}
 										
 
 void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch)
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 4e514ddfd16..c633e3acdde 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -114,8 +114,6 @@ BOOL		LLViewerObject::sMapDebug = TRUE;
 LLColor4	LLViewerObject::sEditSelectColor(	1.0f, 1.f, 0.f, 0.3f);	// Edit OK
 LLColor4	LLViewerObject::sNoEditSelectColor(	1.0f, 0.f, 0.f, 0.3f);	// Can't edit
 S32			LLViewerObject::sAxisArrowLength(50);
-LLTrace::MemStatHandle	LLViewerObject::sMemStat("LLViewerObject");
-
 
 BOOL		LLViewerObject::sPulseEnabled(FALSE);
 BOOL		LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 5556a4c7d3a..63da7152b38 100755
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -661,7 +661,6 @@ class LLViewerObject
 	LLPointer<class LLHUDIcon> mIcon;
 
 	static			BOOL		sUseSharedDrawables;
-	static	LLTrace::MemStatHandle	sMemStat;
 
 protected:
 	// delete an item in the inventory, but don't tell the
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 60d78890b5f..d87eb5d3db9 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -34,8 +34,6 @@
 #include "llviewerregion.h"
 #include "pipeline.h"
 
-LLTrace::MemStatHandle	LLVOCachePartition::sMemStat("LLVOCachePartition");
-
 BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) 
 {
 	return apr_file->read(src, n_bytes) == n_bytes ;
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index bf75cafac5b..c43c42908f4 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -35,7 +35,6 @@
 
 //---------------------------------------------------------------------------
 // Cache entries
-class LLVOCacheEntry;
 class LLCamera;
 
 class LLVOCacheEntry : public LLViewerOctreeEntryData
@@ -158,8 +157,6 @@ class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTr
 	/*virtual*/ S32 cull(LLCamera &camera);
 	void addOccluders(LLviewerOctreeGroup* gp);
 
-	static	LLTrace::MemStatHandle	sMemStat;
-
 private:	
 	void processOccluders(LLCamera* camera, const LLVector3* region_agent);
 
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index b9712e5e9cd..bd42b59df28 100755
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -35,6 +35,7 @@
 #include "lluuid.h"
 #include "llsdutil.h"
 #include "llregionhandle.h"
+#include "lltracethreadrecorder.h"
 #include "../llvoavatar.h"
 
 namespace LLStatViewer
@@ -231,14 +232,15 @@ namespace tut
 	{
 		tst_viewerassetstats_index()
 		{
-			LLTrace::init();
+			LLTrace::set_master_thread_recorder(&mThreadRecorder);
 		}
 
 		~tst_viewerassetstats_index()
 		{
-			LLTrace::cleanup();
+			LLTrace::set_master_thread_recorder(NULL);
 		}
 
+		LLTrace::ThreadRecorder mThreadRecorder;
 	};
 	typedef test_group<tst_viewerassetstats_index> tst_viewerassetstats_index_t;
 	typedef tst_viewerassetstats_index_t::object tst_viewerassetstats_index_object_t;
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 28de88201c2..10f71a2843e 100755
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -41,6 +41,7 @@
 #include "stringize.h"
 #include "namedtempfile.h"
 #include "lltrace.h"
+#include "lltracethreadrecorder.h"
 
 #include "apr_pools.h"
 #include "apr_getopt.h"
@@ -483,6 +484,8 @@ void wouldHaveCrashed(const std::string& message)
 	tut::fail("llerrs message: " + message);
 }
 
+static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
+
 int main(int argc, char **argv)
 {
 	// The following line must be executed to initialize Google Mock
@@ -515,7 +518,11 @@ int main(int argc, char **argv)
 
 	ll_init_apr();
 	
-	LLTrace::init();
+	if (!sMasterThreadRecorder)
+	{
+		sMasterThreadRecorder = new LLTrace::ThreadRecorder();
+		LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
+	}
 	apr_getopt_t* os = NULL;
 	if(APR_SUCCESS != apr_getopt_init(&os, gAPRPoolp, argc, argv))
 	{
-- 
GitLab