From 62fcbb063a191fa4789145c3937e7bef6ce544bd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Sep 2012 18:49:28 -0700
Subject: [PATCH] SH-3275 WIP Run viewer metrics for object update messages
 first pass at LLTrace framework

---
 indra/llcommon/CMakeLists.txt  |   1 +
 indra/llcommon/llfasttimer.cpp |  12 ++-
 indra/llcommon/llfasttimer.h   |   9 +-
 indra/llcommon/lltrace.h       | 169 +++++++++++++++++++++++++++++++++
 4 files changed, 182 insertions(+), 9 deletions(-)
 create mode 100644 indra/llcommon/lltrace.h

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 87fffec0c39..05477c5fa6b 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -238,6 +238,7 @@ set(llcommon_HEADER_FILES
     llthread.h
     llthreadsafequeue.h
     lltimer.h
+    lltrace.h
     lltreeiterators.h
     lltypeinfolookup.h
     lluri.h
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 6970c290924..939e332c3b1 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -216,7 +216,7 @@ LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
 :	mName(name),
 	mCollapsed(true),
 	mParent(NULL),
-	mTotalTimeCounter(0),
+	mTreeTimeCounter(0),
 	mCountAverage(0),
 	mCallAverage(0),
 	mNeedsSorting(false),
@@ -389,6 +389,8 @@ void LLFastTimer::NamedTimer::accumulateTimings()
 		U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
 		cur_data->mChildTime = 0;
 		cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
+		cur_timer->mFrameState->mTotalTimeCounter += cumulative_time_delta;
+
 		cur_timer->mStartTime = cur_time;
 
 		cur_data = &cur_timer->mLastTimerData;
@@ -403,10 +405,10 @@ void LLFastTimer::NamedTimer::accumulateTimings()
 		++it)
 	{
 		NamedTimer* timerp = (*it);
-		timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;
+		timerp->mTreeTimeCounter = timerp->getFrameState().mSelfTimeCounter;
 		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
 		{
-			timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter;
+			timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
 		}
 
 		S32 cur_frame = sCurFrameIndex;
@@ -415,8 +417,8 @@ void LLFastTimer::NamedTimer::accumulateTimings()
 			// update timer history
 			int hidx = cur_frame % HISTORY_NUM;
 
-			timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter;
-			timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1);
+			timerp->mCountHistory[hidx] = timerp->mTreeTimeCounter;
+			timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTreeTimeCounter) / (cur_frame+1);
 			timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls;
 			timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1);
 		}
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index e42e549df58..061a37ae316 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -45,18 +45,17 @@ LL_COMMON_API void assert_main_thread();
 class LL_COMMON_API LLFastTimer
 {
 public:
-	class NamedTimer;
-
 	struct LL_COMMON_API FrameState
 	{
 		FrameState();
 		void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; }
 
 		U32 				mSelfTimeCounter;
+		U32 				mTotalTimeCounter;
 		U32 				mCalls;
 		FrameState*			mParent;		// info for caller timer
 		FrameState*			mLastCaller;	// used to bootstrap tree construction
-		NamedTimer*			mTimer;
+		class NamedTimer*	mTimer;
 		U16					mActiveCount;	// number of timers with this ID active on stack
 		bool				mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame
 	};
@@ -120,7 +119,8 @@ class LL_COMMON_API LLFastTimer
 
 		std::string	mName;
 
-		U32 		mTotalTimeCounter;
+		// sum of recorded self time and tree time of all children timers (might not match actual recorded time of children if topology is incomplete
+		U32 		mTreeTimeCounter; 
 
 		U32 		mCountAverage;
 		U32			mCallAverage;
@@ -186,6 +186,7 @@ class LL_COMMON_API LLFastTimer
 		U32 total_time = getCPUClockCount32() - mStartTime;
 
 		frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
+		frame_state->mTotalTimeCounter += total_time;
 		frame_state->mActiveCount--;
 
 		// store last caller to bootstrap tree creation
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
new file mode 100644
index 00000000000..3d3ee18100c
--- /dev/null
+++ b/indra/llcommon/lltrace.h
@@ -0,0 +1,169 @@
+/** 
+ * @file lltrace.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACE_H
+#define LL_LLTRACE_H
+
+namespace LLTrace
+{
+	class Stat
+	{
+	public:
+		Stat(const char* name)
+		:	mName(name)
+		{}
+		void record() {}
+		void record(int value) {}
+		void record(float value) {}
+	private:
+		const std::string mName;
+	};
+
+	class BlockTimer
+	{
+	public:
+		BlockTimer(const char* name)
+		:	mName(name)
+		{}
+
+		struct Accumulator
+		{
+			U32 						mSelfTimeCounter;
+			U32 						mTotalTimeCounter;
+			U32 						mCalls;
+			Accumulator*				mParent;		// info for caller timer
+			Accumulator*				mLastCaller;	// used to bootstrap tree construction
+			const BlockTimer*			mTimer;			// points to block timer associated with this storage
+			U16							mActiveCount;	// number of timers with this ID active on stack
+			bool						mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame
+			std::vector<Accumulator*>	mChildren;		// currently assumed child timers
+		};
+
+		struct RecorderHead
+		{
+			struct Recorder*	mRecorder;
+			Accumulator*		mAccumulator;
+			U32					mChildTime;
+		};
+
+		struct Recorder
+		{
+			LL_FORCE_INLINE Recorder(BlockTimer& block_timer)
+			:	mLastHead(sRecorderHead)
+			{
+				mStartTime = getCPUClockCount32();
+				Accumulator* accumulator = ???; // get per-thread accumulator
+				accumulator->mActiveCount++;
+				accumulator->mCalls++;
+				accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
+
+				// push new timer on stack
+				sRecorderHead->mRecorder = this;
+				sRecorderHead->mAccumulator = accumulator;
+				sRecorderHead->mChildTime = 0;
+			}
+
+			LL_FORCE_INLINE ~Recorder()
+			{
+				U32 total_time = getCPUClockCount32() - mStartTime;
+
+				Accumulator* accumulator = sRecorderHead->mAccumulator;
+				accumulator->mSelfTimeCounter += total_time- sRecorderHead.mChildTime;
+				accumulator->mTotalTimeCounter += total_time;
+				accumulator->mActiveCount--;
+
+				accumulator->mLastCaller = mLastHead->mAccumulator;
+				mLastHead->mChildTime += total_time;
+
+				// pop stack
+				sRecorderHead = mLastHead;
+			}
+
+			AccumulatorHead mLastHead;
+			U32 mStartTime;
+		};
+
+	private:
+		U32 getCPUClockCount32()
+		{
+			U32 ret_val;
+			__asm
+			{
+				_emit   0x0f
+					_emit   0x31
+					shr eax,8
+					shl edx,24
+					or eax, edx
+					mov dword ptr [ret_val], eax
+			}
+			return ret_val;
+		}
+
+		// return full timer value, *not* shifted by 8 bits
+		static U64 getCPUClockCount64()
+		{
+			U64 ret_val;
+			__asm
+			{
+				_emit   0x0f
+					_emit   0x31
+					mov eax,eax
+					mov edx,edx
+					mov dword ptr [ret_val+4], edx
+					mov dword ptr [ret_val], eax
+			}
+			return ret_val;
+		}
+
+		const std::string mName;
+		static RecorderHead* sRecorderHead;
+	};
+
+	BlockTimer::RecorderHead BlockTimer::sRecorderHead;
+
+	class TimeInterval 
+	{
+	public:
+		void start() {}
+		void stop() {}
+		void resume() {}
+	};
+
+	class SamplingTimeInterval
+	{
+	public:
+		void start() {}
+		void stop() {}
+		void resume() {}
+	};
+
+}
+
+#define TOKEN_PASTE_ACTUAL(x, y) x##y
+#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);
+
+#endif // LL_LLTRACE_H
-- 
GitLab