Commits

davep committed c213402 Draft Merge

Comments (0)

Files changed (213)

           </map>
         </map>
       </map>
+      <key>nvapi</key>
+      <map>
+        <key>license</key>
+        <string>NVAPI</string>
+        <key>license_file</key>
+        <string>LICENSES/NVAPI_SDK_License_Agreement.pdf</string>
+        <key>name</key>
+        <string>nvapi</string>
+        <key>platforms</key>
+        <map>
+          <key>windows</key>
+          <map>
+            <key>archive</key>
+            <map>
+              <key>hash</key>
+              <string>baf519d36dffe4e4a59471450e391d01</string>
+              <key>url</key>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-nvapi/rev/267102/arch/CYGWIN/installer/nvapi-304-windows-20121116.tar.bz2</string>
+            </map>
+            <key>name</key>
+            <string>windows</string>
+          </map>
+        </map>
+      </map>
       <key>ogg-vorbis</key>
       <map>
         <key>license</key>

doc/contributions.txt

 	VWR-1358
 	VWR-2041
 Darien Caldwell
+	SH-3055
 Dartagan Shepherd
 Debs Regent
 Decro Schmooz
 Nick Rhodes
 Nicky Dasmijn
 	VWR-29228
+	MAINT-873
 Nicky Perian
 	OPEN-1
 	STORM-1087
 	SNOW-240
 Sheet Spotter
 Shnurui Troughton
+Shyotl Kuhr
+	MAINT-1138
 Siana Gearz
 	STORM-960
 	STORM-1088
+	MAINT-1138
 sicarius Thorne
 Sicarius Toxx
 SignpostMarv Martin
 Whimsy Winx
 Whirly Fizzle
 	STORM-1895
+	MAINT-873
 Whoops Babii
 	VWR-631
 	VWR-1640

indra/cmake/GooglePerfTools.cmake

File contents unchanged.

indra/cmake/LLAddBuildTest.cmake

   if (WINDOWS)
     set_target_properties(INTEGRATION_TEST_${testname}
       PROPERTIES 
-      LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:__tcmalloc"
+      LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS"
       LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
       LINK_FLAGS_RELEASE ""
       )
   if (WINDOWS)
     SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname}
         PROPERTIES
-        LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}"
+        LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS"
         LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
         LINK_FLAGS_RELEASE ""
         )

indra/cmake/LLCommon.cmake

     set(LLCOMMON_LIBRARIES llcommon)
 endif (LINUX)
 
-add_definitions(${TCMALLOC_FLAG})
+# add_definitions(${TCMALLOC_FLAG})
 
 set(LLCOMMON_LINK_SHARED OFF CACHE BOOL "Build the llcommon target as a static library.")
 if(LLCOMMON_LINK_SHARED)

indra/cmake/NVAPI.cmake

+# -*- cmake -*-
+include(Prebuilt)
+
+set(NVAPI ON CACHE BOOL "Use NVAPI.")
+
+if (NVAPI)
+  if (WINDOWS)
+    use_prebuilt_binary(nvapi)
+    set(NVAPI_LIBRARY nvapi)
+  else (WINDOWS)
+    set(NVAPI_LIBRARY "")
+  endif (WINDOWS)
+else (NVAPI)
+  set(NVAPI_LIBRARY "")
+endif (NVAPI)
+

indra/llcharacter/llbvhconsts.h

 #ifndef LL_LLBVHCONSTS_H
 #define LL_LLBVHCONSTS_H
 
-const F32 MAX_ANIM_DURATION = 30.f;
+const F32 MAX_ANIM_DURATION = 60.f;
 
 typedef enum e_constraint_type
 	{

indra/llcharacter/llmotioncontroller.cpp

 //-----------------------------------------------------------------------------
 #include "linden_common.h"
 
-#include "llmemtype.h"
-
 #include "llmotioncontroller.h"
 #include "llkeyframemotion.h"
 #include "llmath.h"
 //-----------------------------------------------------------------------------
 // Constants and statics
 //-----------------------------------------------------------------------------
+F32 LLMotionController::sCurrentTimeFactor = 1.f;
 LLMotionRegistry LLMotionController::sRegistry;
 
 //-----------------------------------------------------------------------------
 // Class Constructor
 //-----------------------------------------------------------------------------
 LLMotionController::LLMotionController()
-	: mTimeFactor(1.f),
+	: mTimeFactor(sCurrentTimeFactor),
 	  mCharacter(NULL),
 	  mAnimTime(0.f),
 	  mPrevTimerElapsed(0.f),
 //-----------------------------------------------------------------------------
 LLMotion* LLMotionController::createMotion( const LLUUID &id )
 {
-	LLMemType mt(LLMemType::MTYPE_ANIMATION);
 	// do we have an instance of this motion for this character?
 	LLMotion *motion = findMotion(id);
 

indra/llcharacter/llmotioncontroller.h

 
 	const LLFrameTimer& getFrameTimer() { return mTimer; }
 
+	static F32	getCurrentTimeFactor()				{ return sCurrentTimeFactor;	};
+	static void setCurrentTimeFactor(F32 factor)	{ sCurrentTimeFactor = factor;	};
+
 protected:
 	// internal operations act on motion instances directly
 	// as there can be duplicate motions per id during blending overlap
 	void deactivateStoppedMotions();
 
 protected:
-	F32					mTimeFactor;
+	F32					mTimeFactor;			// 1.f for normal speed
+	static F32			sCurrentTimeFactor;		// Value to use for initialization
 	static LLMotionRegistry	sRegistry;
 	LLPoseBlender		mPoseBlender;
 

indra/llcharacter/llvisualparam.h

 // An interface class for a generalized parametric modification of the avatar mesh
 // Contains data that is specific to each Avatar
 //-----------------------------------------------------------------------------
+LL_ALIGN_PREFIX(16)
 class LLVisualParam
 {
 public:
 
 	S32					mID;				// id for storing weight/morphtarget compares compactly
 	LLVisualParamInfo	*mInfo;
-};
+} LL_ALIGN_POSTFIX(16);
 
 #endif // LL_LLVisualParam_H

indra/llcommon/CMakeLists.txt

     lleventfilter.cpp
     llevents.cpp
     lleventtimer.cpp
-    llfasttimer_class.cpp
+    llfasttimer.cpp
     llfile.cpp
     llfindlocale.cpp
     llfixedbuffer.cpp
     llmd5.cpp
     llmemory.cpp
     llmemorystream.cpp
-    llmemtype.cpp
     llmetrics.cpp
     llmetricperformancetester.cpp
     llmortician.cpp
     lleventemitter.h
     llextendedstatus.h
     llfasttimer.h
-    llfasttimer_class.h
     llfile.h
     llfindlocale.h
     llfixedbuffer.h
     llmd5.h
     llmemory.h
     llmemorystream.h
-    llmemtype.h
     llmetrics.h
     llmetricperformancetester.h
     llmortician.h

indra/llcommon/llallocator.cpp

 DECLARE_bool(heap_profile_use_stack_trace);
 //DECLARE_double(tcmalloc_release_rate);
 
-// static
-void LLAllocator::pushMemType(S32 type)
-{
-    if(isProfiling())
-    {
-    	PushMemType(type);
-    }
-}
-
-// static
-S32 LLAllocator::popMemType()
-{
-    if (isProfiling())
-    {
-    	return PopMemType();
-    }
-    else
-    {
-        return -1;
-    }
-}
-
 void LLAllocator::setProfilingEnabled(bool should_enable)
 {
     // NULL disables dumping to disk
 // stub implementations for when tcmalloc is disabled
 //
 
-// static
-void LLAllocator::pushMemType(S32 type)
-{
-}
-
-// static
-S32 LLAllocator::popMemType()
-{
-    return -1;
-}
-
 void LLAllocator::setProfilingEnabled(bool should_enable)
 {
 }

indra/llcommon/llallocator.h

 
 #include <string>
 
-#include "llmemtype.h"
 #include "llallocator_heap_profile.h"
 
 class LL_COMMON_API LLAllocator {
     friend class LLMemoryView;
-    friend class LLMemType;
-
-private:
-	static void pushMemType(S32 type);
-	static S32 popMemType();
 
 public:
     void setProfilingEnabled(bool should_enable);

indra/llcommon/llfasttimer.cpp

+/** 
+ * @file llfasttimer.cpp
+ * @brief Implementation of the fast timer.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+#include "linden_common.h"
+
+#include "llfasttimer.h"
+
+#include "llmemory.h"
+#include "llprocessor.h"
+#include "llsingleton.h"
+#include "lltreeiterators.h"
+#include "llsdserialize.h"
+
+#include <boost/bind.hpp>
+
+
+#if LL_WINDOWS
+#include "lltimer.h"
+#elif LL_LINUX || LL_SOLARIS
+#include <sys/time.h>
+#include <sched.h>
+#include "lltimer.h"
+#elif LL_DARWIN
+#include <sys/time.h>
+#include "lltimer.h"	// get_clock_count()
+#else 
+#error "architecture not supported"
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// statics
+
+S32 LLFastTimer::sCurFrameIndex = -1;
+S32 LLFastTimer::sLastFrameIndex = -1;
+U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64();
+bool LLFastTimer::sPauseHistory = 0;
+bool LLFastTimer::sResetHistory = 0;
+LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
+BOOL LLFastTimer::sLog = FALSE;
+std::string LLFastTimer::sLogName = "";
+BOOL LLFastTimer::sMetricLog = FALSE;
+LLMutex* LLFastTimer::sLogLock = NULL;
+std::queue<LLSD> LLFastTimer::sLogQueue;
+
+#if LL_LINUX || LL_SOLARIS
+U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution
+#else
+U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution
+#endif
+
+// FIXME: move these declarations to the relevant modules
+
+// helper functions
+typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
+
+static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id) 
+{ 
+	return timer_tree_bottom_up_iterator_t(&id, 
+							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+}
+
+static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() 
+{ 
+	return timer_tree_bottom_up_iterator_t(); 
+}
+
+typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t;
+
+
+static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id) 
+{ 
+	return timer_tree_dfs_iterator_t(&id, 
+		boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+}
+
+static timer_tree_dfs_iterator_t end_timer_tree() 
+{ 
+	return timer_tree_dfs_iterator_t(); 
+}
+
+// factory class that creates NamedTimers via static DeclareTimer objects
+class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
+{
+public:
+	NamedTimerFactory()
+	:	mTimerRoot(NULL)
+	{}
+
+	/*virtual */ void initSingleton()
+	{
+		mTimerRoot = new LLFastTimer::NamedTimer("root");
+		mRootFrameState.setNamedTimer(mTimerRoot);
+		mTimerRoot->setFrameState(&mRootFrameState);
+		mTimerRoot->mParent = mTimerRoot;
+		mTimerRoot->setCollapsed(false);
+		mRootFrameState.mParent = &mRootFrameState;
+	}
+
+	~NamedTimerFactory()
+	{
+		std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer());
+
+		delete mTimerRoot;
+	}
+
+	LLFastTimer::NamedTimer& createNamedTimer(const std::string& name, LLFastTimer::FrameState* state)
+	{
+		LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name);
+		timer->setFrameState(state);
+		timer->setParent(mTimerRoot);
+		mTimers.insert(std::make_pair(name, timer));
+
+		return *timer;
+	}
+
+	LLFastTimer::NamedTimer* getTimerByName(const std::string& name)
+	{
+		timer_map_t::iterator found_it = mTimers.find(name);
+		if (found_it != mTimers.end())
+		{
+			return found_it->second;
+		}
+		return NULL;
+	}
+
+	LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; }
+
+	typedef std::multimap<std::string, LLFastTimer::NamedTimer*> timer_map_t;
+	timer_map_t::iterator beginTimers() { return mTimers.begin(); }
+	timer_map_t::iterator endTimers() { return mTimers.end(); }
+	S32 timerCount() { return mTimers.size(); }
+
+private:
+	timer_map_t mTimers;
+
+	LLFastTimer::NamedTimer*		mTimerRoot;
+	LLFastTimer::FrameState			mRootFrameState;
+};
+
+LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open )
+:	mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))
+{
+	mTimer.setCollapsed(!open);
+}
+
+LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
+:	mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))
+{
+}
+
+//static
+#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
+{
+	return sClockResolution >> 8;
+}
+#else // windows or x86-mac or x86-linux or x86-solaris
+U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
+{
+#if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
+	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
+	static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0);
+
+	// we drop the low-order byte in our timers, so report a lower frequency
+#else
+	// If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
+	// Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
+	// since that would change displayed MHz stats for CPUs
+	static bool firstcall = true;
+	static U64 sCPUClockFrequency;
+	if (firstcall)
+	{
+		QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
+		firstcall = false;
+	}
+#endif
+	return sCPUClockFrequency >> 8;
+}
+#endif
+
+LLFastTimer::FrameState::FrameState()
+:	mActiveCount(0),
+	mCalls(0),
+	mSelfTimeCounter(0),
+	mParent(NULL),
+	mLastCaller(NULL),
+	mMoveUpTree(false)
+{}
+
+
+LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
+:	mName(name),
+	mCollapsed(true),
+	mParent(NULL),
+	mTotalTimeCounter(0),
+	mCountAverage(0),
+	mCallAverage(0),
+	mNeedsSorting(false),
+	mFrameState(NULL)
+{
+	mCountHistory = new U32[HISTORY_NUM];
+	memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
+	mCallHistory = new U32[HISTORY_NUM];
+	memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
+}
+
+LLFastTimer::NamedTimer::~NamedTimer()
+{
+	delete[] mCountHistory;
+	delete[] mCallHistory;
+}
+
+std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
+{
+	F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
+	if (history_idx < 0)
+	{
+		// by default, show average number of call
+		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage());
+	}
+	else
+	{
+		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
+	}
+}
+
+void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
+{
+	llassert_always(parent != this);
+	llassert_always(parent != NULL);
+
+	if (mParent)
+	{
+		// subtract our accumulated from previous parent
+		for (S32 i = 0; i < HISTORY_NUM; i++)
+		{
+			mParent->mCountHistory[i] -= mCountHistory[i];
+		}
+
+		// subtract average timing from previous parent
+		mParent->mCountAverage -= mCountAverage;
+
+		std::vector<NamedTimer*>& children = mParent->getChildren();
+		std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
+		if (found_it != children.end())
+		{
+			children.erase(found_it);
+		}
+	}
+
+	mParent = parent;
+	if (parent)
+	{
+		getFrameState().mParent = &parent->getFrameState();
+		parent->getChildren().push_back(this);
+		parent->mNeedsSorting = true;
+	}
+}
+
+S32 LLFastTimer::NamedTimer::getDepth()
+{
+	S32 depth = 0;
+	NamedTimer* timerp = mParent;
+	while(timerp)
+	{
+		depth++;
+		if (timerp->getParent() == timerp) break;
+		timerp = timerp->mParent;
+	}
+	return depth;
+}
+
+// static
+void LLFastTimer::NamedTimer::processTimes()
+{
+	if (sCurFrameIndex < 0) return;
+
+	buildHierarchy();
+	accumulateTimings();
+}
+
+// sort child timers by name
+struct SortTimerByName
+{
+	bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2)
+	{
+		return i1->getName() < i2->getName();
+	}
+};
+
+//static
+void LLFastTimer::NamedTimer::buildHierarchy()
+{
+	if (sCurFrameIndex < 0 ) return;
+
+	// set up initial tree
+	{
+		for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+		{
+			NamedTimer& timer = *it;
+			if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
+			
+			// bootstrap tree construction by attaching to last timer to be on stack
+			// when this timer was called
+			if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
+			{
+				timer.setParent(timer.getFrameState().mLastCaller->mTimer);
+				// no need to push up tree on first use, flag can be set spuriously
+				timer.getFrameState().mMoveUpTree = false;
+			}
+		}
+	}
+
+	// bump timers up tree if they've been flagged as being in the wrong place
+	// do this in a bottom up order to promote descendants first before promoting ancestors
+	// this preserves partial order derived from current frame's observations
+	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
+		it != end_timer_tree_bottom_up();
+		++it)
+	{
+		NamedTimer* timerp = *it;
+		// skip root timer
+		if (timerp == NamedTimerFactory::instance().getRootTimer()) continue;
+
+		if (timerp->getFrameState().mMoveUpTree)
+		{
+			// since ancestors have already been visited, reparenting won't affect tree traversal
+			//step up tree, bringing our descendants with us
+			LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
+				" to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
+			timerp->setParent(timerp->getParent()->getParent());
+			timerp->getFrameState().mMoveUpTree = false;
+
+			// don't bubble up any ancestors until descendants are done bubbling up
+			it.skipAncestors();
+		}
+	}
+
+	// sort timers by time last called, so call graph makes sense
+	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+		it != end_timer_tree();
+		++it)
+	{
+		NamedTimer* timerp = (*it);
+		if (timerp->mNeedsSorting)
+		{
+			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
+		}
+		timerp->mNeedsSorting = false;
+	}
+}
+
+//static
+void LLFastTimer::NamedTimer::accumulateTimings()
+{
+	U32 cur_time = getCPUClockCount32();
+
+	// walk up stack of active timers and accumulate current time while leaving timing structures active
+	LLFastTimer* cur_timer = sCurTimerData.mCurTimer;
+	// root defined by parent pointing to self
+	CurTimerData* cur_data = &sCurTimerData;
+	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
+	{
+		U32 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+		U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
+		cur_data->mChildTime = 0;
+		cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
+		cur_timer->mStartTime = cur_time;
+
+		cur_data = &cur_timer->mLastTimerData;
+		cur_data->mChildTime += cumulative_time_delta;
+
+		cur_timer = cur_timer->mLastTimerData.mCurTimer;
+	}
+
+	// traverse tree in DFS post order, or bottom up
+	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
+		it != end_timer_tree_bottom_up();
+		++it)
+	{
+		NamedTimer* timerp = (*it);
+		timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;
+		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
+		{
+			timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter;
+		}
+
+		S32 cur_frame = sCurFrameIndex;
+		if (cur_frame >= 0)
+		{
+			// 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->mCallHistory[hidx] = timerp->getFrameState().mCalls;
+			timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1);
+		}
+	}
+}
+
+// static
+void LLFastTimer::NamedTimer::resetFrame()
+{
+	if (sLog)
+	{ //output current frame counts to performance log
+
+		static S32 call_count = 0;
+		if (call_count % 100 == 0)
+		{
+			LL_DEBUGS("FastTimers") << "countsPerSecond (32 bit): " << countsPerSecond() << LL_ENDL;
+			LL_DEBUGS("FastTimers") << "get_clock_count (64 bit): " << get_clock_count() << llendl;
+			LL_DEBUGS("FastTimers") << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << LL_ENDL;
+			LL_DEBUGS("FastTimers") << "getCPUClockCount32() " << getCPUClockCount32() << LL_ENDL;
+			LL_DEBUGS("FastTimers") << "getCPUClockCount64() " << getCPUClockCount64() << LL_ENDL;
+			LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64())/((F64)LLProcessorInfo().getCPUFrequency()*1000000.0) << LL_ENDL;
+		}
+		call_count++;
+
+		F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency
+
+		F64 total_time = 0;
+		LLSD sd;
+
+		{
+			for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+			{
+				NamedTimer& timer = *it;
+				FrameState& info = timer.getFrameState();
+				sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);	
+				sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
+				
+				// computing total time here because getting the root timer's getCountHistory
+				// doesn't work correctly on the first frame
+				total_time = total_time + info.mSelfTimeCounter * iclock_freq;
+			}
+		}
+
+		sd["Total"]["Time"] = (LLSD::Real) total_time;
+		sd["Total"]["Calls"] = (LLSD::Integer) 1;
+
+		{		
+			LLMutexLock lock(sLogLock);
+			sLogQueue.push(sd);
+		}
+	}
+
+	// reset for next frame
+	for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+	{
+		NamedTimer& timer = *it;
+			
+		FrameState& info = timer.getFrameState();
+		info.mSelfTimeCounter = 0;
+		info.mCalls = 0;
+		info.mLastCaller = NULL;
+		info.mMoveUpTree = false;
+		// update parent pointer in timer state struct
+		if (timer.mParent)
+		{
+			info.mParent = &timer.mParent->getFrameState();
+		}
+	}
+}
+
+//static
+void LLFastTimer::NamedTimer::reset()
+{
+	resetFrame(); // reset frame data
+
+	// walk up stack of active timers and reset start times to current time
+	// effectively zeroing out any accumulated time
+	U32 cur_time = getCPUClockCount32();
+
+	// root defined by parent pointing to self
+	CurTimerData* cur_data = &sCurTimerData;
+	LLFastTimer* cur_timer = cur_data->mCurTimer;
+	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
+	{
+		cur_timer->mStartTime = cur_time;
+		cur_data->mChildTime = 0;
+
+		cur_data = &cur_timer->mLastTimerData;
+		cur_timer = cur_data->mCurTimer;
+	}
+
+	// reset all history
+	{
+		for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+		{
+			NamedTimer& timer = *it;
+			if (&timer != NamedTimerFactory::instance().getRootTimer()) 
+			{
+				timer.setParent(NamedTimerFactory::instance().getRootTimer());
+			}
+			
+			timer.mCountAverage = 0;
+			timer.mCallAverage = 0;
+			memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
+			memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
+		}
+	}
+
+	sLastFrameIndex = 0;
+	sCurFrameIndex = 0;
+}
+
+U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const
+{
+	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
+	return mCountHistory[history_idx];
+}
+
+U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const
+{
+	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
+	return mCallHistory[history_idx];
+}
+
+LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const
+{
+	return *mFrameState;
+}
+
+std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren()
+{ 
+	return mChildren.begin(); 
+}
+
+std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren()
+{
+	return mChildren.end();
+}
+
+std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren()
+{
+	return mChildren;
+}
+
+//static
+void LLFastTimer::nextFrame()
+{
+	countsPerSecond(); // good place to calculate clock frequency
+	U64 frame_time = getCPUClockCount64();
+	if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
+	{
+		llinfos << "Slow frame, fast timers inaccurate" << llendl;
+	}
+
+	if (!sPauseHistory)
+	{
+		NamedTimer::processTimes();
+		sLastFrameIndex = sCurFrameIndex++;
+	}
+	
+	// get ready for next frame
+	NamedTimer::resetFrame();
+	sLastFrameTime = frame_time;
+}
+
+//static
+void LLFastTimer::dumpCurTimes()
+{
+	// accumulate timings, etc.
+	NamedTimer::processTimes();
+	
+	F64 clock_freq = (F64)countsPerSecond();
+	F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds
+
+	// walk over timers in depth order and output timings
+	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+		it != end_timer_tree();
+		++it)
+	{
+		NamedTimer* timerp = (*it);
+		F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq);
+		// Don't bother with really brief times, keep output concise
+		if (total_time_ms < 0.1) continue;
+
+		std::ostringstream out_str;
+		for (S32 i = 0; i < timerp->getDepth(); i++)
+		{
+			out_str << "\t";
+		}
+
+
+		out_str << timerp->getName() << " " 
+			<< std::setprecision(3) << total_time_ms << " ms, "
+			<< timerp->getHistoricalCalls(0) << " calls";
+
+		llinfos << out_str.str() << llendl;
+	}
+}
+
+//static 
+void LLFastTimer::reset()
+{
+	NamedTimer::reset();
+}
+
+
+//static
+void LLFastTimer::writeLog(std::ostream& os)
+{
+	while (!sLogQueue.empty())
+	{
+		LLSD& sd = sLogQueue.front();
+		LLSDSerialize::toXML(sd, os);
+		LLMutexLock lock(sLogLock);
+		sLogQueue.pop();
+	}
+}
+
+//static
+const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name)
+{
+	return NamedTimerFactory::instance().getTimerByName(name);
+}
+
+LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state)
+:	mFrameState(state)
+{
+	U32 start_time = getCPUClockCount32();
+	mStartTime = start_time;
+	mFrameState->mActiveCount++;
+	LLFastTimer::sCurTimerData.mCurTimer = this;
+	LLFastTimer::sCurTimerData.mFrameState = mFrameState;
+	LLFastTimer::sCurTimerData.mChildTime = 0;
+	mLastTimerData = LLFastTimer::sCurTimerData;
+}
+
+

indra/llcommon/llfasttimer.h

 /**
  * @file llfasttimer.h
- * @brief Inline implementations of fast timers.
+ * @brief Declaration of a fast timer.
  *
  * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  * Second Life Viewer Source Code
 #ifndef LL_FASTTIMER_H
 #define LL_FASTTIMER_H
 
-// Implementation of getCPUClockCount32() and getCPUClockCount64 are now in llfastertimer_class.cpp.
+#include "llinstancetracker.h"
 
-// pull in the actual class definition
-#include "llfasttimer_class.h"
+#define FAST_TIMER_ON 1
+#define DEBUG_FAST_TIMER_THREADS 1
+
+class LLMutex;
+
+#include <queue>
+#include "llsd.h"
+
+#define LL_FASTTIMER_USE_RDTSC 1
+
+
+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 				mCalls;
+		FrameState*			mParent;		// info for caller timer
+		FrameState*			mLastCaller;	// used to bootstrap tree construction
+		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
+	};
+
+	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
+	class LL_COMMON_API NamedTimer
+	:	public LLInstanceTracker<NamedTimer>
+	{
+		friend class DeclareTimer;
+	public:
+		~NamedTimer();
+
+		enum { HISTORY_NUM = 300 };
+
+		const std::string& getName() const { return mName; }
+		NamedTimer* getParent() const { return mParent; }
+		void setParent(NamedTimer* parent);
+		S32 getDepth();
+		std::string getToolTip(S32 history_index = -1);
+
+		typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
+		child_const_iter beginChildren();
+		child_const_iter endChildren();
+		std::vector<NamedTimer*>& getChildren();
+
+		void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
+		bool getCollapsed() const { return mCollapsed; }
+
+		U32 getCountAverage() const { return mCountAverage; }
+		U32 getCallAverage() const { return mCallAverage; }
+
+		U32 getHistoricalCount(S32 history_index = 0) const;
+		U32 getHistoricalCalls(S32 history_index = 0) const;
+
+		void setFrameState(FrameState* state) { mFrameState = state; state->setNamedTimer(this); }
+		FrameState& getFrameState() const;
+
+	private:
+		friend class LLFastTimer;
+		friend class NamedTimerFactory;
+
+		//
+		// methods
+		//
+		NamedTimer(const std::string& name);
+		// recursive call to gather total time from children
+		static void accumulateTimings();
+
+		// updates cumulative times and hierarchy,
+		// can be called multiple times in a frame, at any point
+		static void processTimes();
+
+		static void buildHierarchy();
+		static void resetFrame();
+		static void reset();
+
+		//
+		// members
+		//
+		FrameState*		mFrameState;
+
+		std::string	mName;
+
+		U32 		mTotalTimeCounter;
+
+		U32 		mCountAverage;
+		U32			mCallAverage;
+
+		U32*		mCountHistory;
+		U32*		mCallHistory;
+
+		// tree structure
+		NamedTimer*					mParent;				// NamedTimer of caller(parent)
+		std::vector<NamedTimer*>	mChildren;
+		bool						mCollapsed;				// don't show children
+		bool						mNeedsSorting;			// sort children whenever child added
+	};
+
+	// used to statically declare a new named timer
+	class LL_COMMON_API DeclareTimer
+	:	public LLInstanceTracker<DeclareTimer>
+	{
+		friend class LLFastTimer;
+	public:
+		DeclareTimer(const std::string& name, bool open);
+		DeclareTimer(const std::string& name);
+
+		NamedTimer& getNamedTimer() { return mTimer; }
+
+	private:
+		FrameState		mFrameState;
+		NamedTimer&		mTimer;
+	};
+
+public:
+	LLFastTimer(LLFastTimer::FrameState* state);
+
+	LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer)
+	:	mFrameState(&timer.mFrameState)
+	{
+#if FAST_TIMER_ON
+		LLFastTimer::FrameState* frame_state = mFrameState;
+		mStartTime = getCPUClockCount32();
+
+		frame_state->mActiveCount++;
+		frame_state->mCalls++;
+		// keep current parent as long as it is active when we are
+		frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
+
+		LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData;
+		mLastTimerData = *cur_timer_data;
+		cur_timer_data->mCurTimer = this;
+		cur_timer_data->mFrameState = frame_state;
+		cur_timer_data->mChildTime = 0;
+#endif
+#if DEBUG_FAST_TIMER_THREADS
+#if !LL_RELEASE
+		assert_main_thread();
+#endif
+#endif
+	}
+
+	LL_FORCE_INLINE ~LLFastTimer()
+	{
+#if FAST_TIMER_ON
+		LLFastTimer::FrameState* frame_state = mFrameState;
+		U32 total_time = getCPUClockCount32() - mStartTime;
+
+		frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
+		frame_state->mActiveCount--;
+
+		// store last caller to bootstrap tree creation
+		// do this in the destructor in case of recursion to get topmost caller
+		frame_state->mLastCaller = mLastTimerData.mFrameState;
+
+		// we are only tracking self time, so subtract our total time delta from parents
+		mLastTimerData.mChildTime += total_time;
+
+		LLFastTimer::sCurTimerData = mLastTimerData;
+#endif
+	}
+
+public:
+	static LLMutex*			sLogLock;
+	static std::queue<LLSD> sLogQueue;
+	static BOOL				sLog;
+	static BOOL				sMetricLog;
+	static std::string		sLogName;
+	static bool 			sPauseHistory;
+	static bool 			sResetHistory;
+
+	// call this once a frame to reset timers
+	static void nextFrame();
+
+	// dumps current cumulative frame stats to log
+	// call nextFrame() to reset timers
+	static void dumpCurTimes();
+
+	// call this to reset timer hierarchy, averages, etc.
+	static void reset();
+
+	static U64 countsPerSecond();
+	static S32 getLastFrameIndex() { return sLastFrameIndex; }
+	static S32 getCurFrameIndex() { return sCurFrameIndex; }
+
+	static void writeLog(std::ostream& os);
+	static const NamedTimer* getTimerByName(const std::string& name);
+
+	struct CurTimerData
+	{
+		LLFastTimer*	mCurTimer;
+		FrameState*		mFrameState;
+		U32				mChildTime;
+	};
+	static CurTimerData		sCurTimerData;
+
+private:
+
+
+	//////////////////////////////////////////////////////////////////////////////
+	//
+	// Important note: These implementations must be FAST!
+	//
+
+
+#if LL_WINDOWS
+	//
+	// Windows implementation of CPU clock
+	//
+
+	//
+	// NOTE: put back in when we aren't using platform sdk anymore
+	//
+	// because MS has different signatures for these functions in winnt.h
+	// need to rename them to avoid conflicts
+	//#define _interlockedbittestandset _renamed_interlockedbittestandset
+	//#define _interlockedbittestandreset _renamed_interlockedbittestandreset
+	//#include <intrin.h>
+	//#undef _interlockedbittestandset
+	//#undef _interlockedbittestandreset
+
+	//inline U32 LLFastTimer::getCPUClockCount32()
+	//{
+	//	U64 time_stamp = __rdtsc();
+	//	return (U32)(time_stamp >> 8);
+	//}
+	//
+	//// return full timer value, *not* shifted by 8 bits
+	//inline U64 LLFastTimer::getCPUClockCount64()
+	//{
+	//	return __rdtsc();
+	//}
+
+	// shift off lower 8 bits for lower resolution but longer term timing
+	// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
+#if LL_FASTTIMER_USE_RDTSC
+	static 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;
+	}
+
+#else
+	//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp
+	// These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures.
+	static U32 getCPUClockCount32()
+	{
+		return (U32)(get_clock_count()>>8);
+	}
+
+	static U64 getCPUClockCount64()
+	{
+		return get_clock_count();
+	}
+
+#endif
+
+#endif
+
+
+#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+	//
+	// Linux and Solaris implementation of CPU clock - non-x86.
+	// This is accurate but SLOW!  Only use out of desperation.
+	//
+	// Try to use the MONOTONIC clock if available, this is a constant time counter
+	// with nanosecond resolution (but not necessarily accuracy) and attempts are
+	// made to synchronize this value between cores at kernel start. It should not
+	// be affected by CPU frequency. If not available use the REALTIME clock, but
+	// this may be affected by NTP adjustments or other user activity affecting
+	// the system time.
+	static U64 getCPUClockCount64()
+	{
+		struct timespec tp;
+
+#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time?
+		if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME
+#endif
+			clock_gettime(CLOCK_REALTIME,&tp);
+
+		return (tp.tv_sec*sClockResolution)+tp.tv_nsec;        
+	}
+
+	static U32 getCPUClockCount32()
+	{
+		return (U32)(getCPUClockCount64() >> 8);
+	}
+
+#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+
+
+#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+	//
+	// Mac+Linux+Solaris FAST x86 implementation of CPU clock
+	static U32 getCPUClockCount32()
+	{
+		U64 x;
+		__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+		return (U32)(x >> 8);
+	}
+
+	static U64 getCPUClockCount64()
+	{
+		U64 x;
+		__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+		return x;
+	}
+
+#endif
+
+	static U64 sClockResolution;
+
+	static S32				sCurFrameIndex;
+	static S32				sLastFrameIndex;
+	static U64				sLastFrameTime;
+
+	U32							mStartTime;
+	LLFastTimer::FrameState*	mFrameState;
+	LLFastTimer::CurTimerData	mLastTimerData;
+
+};
+
+typedef class LLFastTimer LLFastTimer;
 
 #endif // LL_LLFASTTIMER_H

indra/llcommon/llfasttimer_class.cpp

-/** 
- * @file llfasttimer_class.cpp
- * @brief Implementation of the fast timer.
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-#include "linden_common.h"
-
-#include "llfasttimer.h"
-
-#include "llmemory.h"
-#include "llprocessor.h"
-#include "llsingleton.h"
-#include "lltreeiterators.h"
-#include "llsdserialize.h"
-
-#include <boost/bind.hpp>
-
-
-#if LL_WINDOWS
-#include "lltimer.h"
-#elif LL_LINUX || LL_SOLARIS
-#include <sys/time.h>
-#include <sched.h>
-#include "lltimer.h"
-#elif LL_DARWIN
-#include <sys/time.h>
-#include "lltimer.h"	// get_clock_count()
-#else 
-#error "architecture not supported"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-// statics
-
-S32 LLFastTimer::sCurFrameIndex = -1;
-S32 LLFastTimer::sLastFrameIndex = -1;
-U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64();
-bool LLFastTimer::sPauseHistory = 0;
-bool LLFastTimer::sResetHistory = 0;
-LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
-BOOL LLFastTimer::sLog = FALSE;
-std::string LLFastTimer::sLogName = "";
-BOOL LLFastTimer::sMetricLog = FALSE;
-LLMutex* LLFastTimer::sLogLock = NULL;
-std::queue<LLSD> LLFastTimer::sLogQueue;
-
-#define USE_RDTSC 0
-
-#if LL_LINUX || LL_SOLARIS
-U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution
-#else
-U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution
-#endif
-
-std::vector<LLFastTimer::FrameState>* LLFastTimer::sTimerInfos = NULL;
-U64				LLFastTimer::sTimerCycles = 0;
-U32				LLFastTimer::sTimerCalls = 0;
-
-
-// FIXME: move these declarations to the relevant modules
-
-// helper functions
-typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
-
-static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id) 
-{ 
-	return timer_tree_bottom_up_iterator_t(&id, 
-							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
-}
-
-static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() 
-{ 
-	return timer_tree_bottom_up_iterator_t(); 
-}
-
-typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t;
-
-
-static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id) 
-{ 
-	return timer_tree_dfs_iterator_t(&id, 
-		boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
-}
-
-static timer_tree_dfs_iterator_t end_timer_tree() 
-{ 
-	return timer_tree_dfs_iterator_t(); 
-}
-
-
-
-// factory class that creates NamedTimers via static DeclareTimer objects
-class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
-{
-public:
-	NamedTimerFactory()
-		: mActiveTimerRoot(NULL),
-		  mTimerRoot(NULL),
-		  mAppTimer(NULL),
-		  mRootFrameState(NULL)
-	{}
-
-	/*virtual */ void initSingleton()
-	{
-		mTimerRoot = new LLFastTimer::NamedTimer("root");
-
-		mActiveTimerRoot = new LLFastTimer::NamedTimer("Frame");
-		mActiveTimerRoot->setCollapsed(false);
-
-		mRootFrameState = new LLFastTimer::FrameState(mActiveTimerRoot);
-		mRootFrameState->mParent = &mTimerRoot->getFrameState();
-		mActiveTimerRoot->setParent(mTimerRoot);
-
-		mAppTimer = new LLFastTimer(mRootFrameState);
-	}
-
-	~NamedTimerFactory()
-	{
-		std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer());
-
-		delete mAppTimer;
-		delete mActiveTimerRoot; 
-		delete mTimerRoot;
-		delete mRootFrameState;
-	}
-
-	LLFastTimer::NamedTimer& createNamedTimer(const std::string& name)
-	{
-		timer_map_t::iterator found_it = mTimers.find(name);
-		if (found_it != mTimers.end())
-		{
-			return *found_it->second;
-		}
-
-		LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name);
-		timer->setParent(mTimerRoot);
-		mTimers.insert(std::make_pair(name, timer));
-
-		return *timer;
-	}
-
-	LLFastTimer::NamedTimer* getTimerByName(const std::string& name)
-	{
-		timer_map_t::iterator found_it = mTimers.find(name);
-		if (found_it != mTimers.end())
-		{
-			return found_it->second;
-		}
-		return NULL;
-	}
-
-	LLFastTimer::NamedTimer* getActiveRootTimer() { return mActiveTimerRoot; }
-	LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; }
-	const LLFastTimer* getAppTimer() { return mAppTimer; }
-	LLFastTimer::FrameState& getRootFrameState() { return *mRootFrameState; }
-
-	typedef std::map<std::string, LLFastTimer::NamedTimer*> timer_map_t;
-	timer_map_t::iterator beginTimers() { return mTimers.begin(); }
-	timer_map_t::iterator endTimers() { return mTimers.end(); }
-	S32 timerCount() { return mTimers.size(); }
-
-private:
-	timer_map_t mTimers;
-
-	LLFastTimer::NamedTimer*		mActiveTimerRoot;
-	LLFastTimer::NamedTimer*		mTimerRoot;
-	LLFastTimer*						mAppTimer;
-	LLFastTimer::FrameState*		mRootFrameState;
-};
-
-void update_cached_pointers_if_changed()
-{
-	// detect when elements have moved and update cached pointers
-	static LLFastTimer::FrameState* sFirstTimerAddress = NULL;
-	if (&*(LLFastTimer::getFrameStateList().begin()) != sFirstTimerAddress)
-	{
-		LLFastTimer::DeclareTimer::updateCachedPointers();
-	}
-	sFirstTimerAddress = &*(LLFastTimer::getFrameStateList().begin());
-}
-
-LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open )
-:	mTimer(NamedTimerFactory::instance().createNamedTimer(name))
-{
-	mTimer.setCollapsed(!open);
-	mFrameState = &mTimer.getFrameState();
-	update_cached_pointers_if_changed();
-}
-
-LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
-:	mTimer(NamedTimerFactory::instance().createNamedTimer(name))
-{
-	mFrameState = &mTimer.getFrameState();
-	update_cached_pointers_if_changed();
-}
-
-// static
-void LLFastTimer::DeclareTimer::updateCachedPointers()
-{
-	// propagate frame state pointers to timer declarations
-	for (instance_iter it = beginInstances(); it != endInstances(); ++it)
-	{
-		// update cached pointer
-		it->mFrameState = &it->mTimer.getFrameState();
-	}
-
-	// also update frame states of timers on stack
-	LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer;
-	while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp)	
-	{
-		cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState();
-		cur_timerp = cur_timerp->mLastTimerData.mCurTimer;
-	}
-}
-
-//static
-#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
-{
-	return sClockResolution >> 8;
-}
-#else // windows or x86-mac or x86-linux or x86-solaris
-U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
-{
-#if USE_RDTSC || !LL_WINDOWS
-	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
-	static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0);
-
-	// we drop the low-order byte in our timers, so report a lower frequency
-#else
-	// If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
-	// Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
-	// since that would change displayed MHz stats for CPUs
-	static bool firstcall = true;
-	static U64 sCPUClockFrequency;
-	if (firstcall)
-	{
-		QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
-		firstcall = false;
-	}
-#endif
-	return sCPUClockFrequency >> 8;
-}
-#endif
-
-LLFastTimer::FrameState::FrameState(LLFastTimer::NamedTimer* timerp)
-:	mActiveCount(0),
-	mCalls(0),
-	mSelfTimeCounter(0),
-	mParent(NULL),
-	mLastCaller(NULL),
-	mMoveUpTree(false),
-	mTimer(timerp)
-{}
-
-
-LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
-:	mName(name),
-	mCollapsed(true),
-	mParent(NULL),
-	mTotalTimeCounter(0),
-	mCountAverage(0),
-	mCallAverage(0),
-	mNeedsSorting(false)
-{
-	info_list_t& frame_state_list = getFrameStateList();
-	mFrameStateIndex = frame_state_list.size();
-	getFrameStateList().push_back(FrameState(this));
-
-	mCountHistory = new U32[HISTORY_NUM];
-	memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
-	mCallHistory = new U32[HISTORY_NUM];
-	memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
-}
-
-LLFastTimer::NamedTimer::~NamedTimer()
-{
-	delete[] mCountHistory;
-	delete[] mCallHistory;
-}
-
-std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
-{
-	F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
-	if (history_idx < 0)
-	{
-		// by default, show average number of call
-		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage());
-	}
-	else
-	{
-		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
-	}
-}
-
-void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
-{
-	llassert_always(parent != this);
-	llassert_always(parent != NULL);
-
-	if (mParent)
-	{
-		// subtract our accumulated from previous parent
-		for (S32 i = 0; i < HISTORY_NUM; i++)
-		{
-			mParent->mCountHistory[i] -= mCountHistory[i];
-		}
-
-		// subtract average timing from previous parent
-		mParent->mCountAverage -= mCountAverage;
-
-		std::vector<NamedTimer*>& children = mParent->getChildren();
-		std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
-		if (found_it != children.end())
-		{
-			children.erase(found_it);
-		}
-	}
-
-	mParent = parent;
-	if (parent)
-	{
-		getFrameState().mParent = &parent->getFrameState();
-		parent->getChildren().push_back(this);
-		parent->mNeedsSorting = true;
-	}
-}
-
-S32 LLFastTimer::NamedTimer::getDepth()
-{
-	S32 depth = 0;
-	NamedTimer* timerp = mParent;
-	while(timerp)
-	{
-		depth++;
-		timerp = timerp->mParent;
-	}
-	return depth;
-}
-
-// static
-void LLFastTimer::NamedTimer::processTimes()
-{
-	if (sCurFrameIndex < 0) return;
-
-	buildHierarchy();
-	accumulateTimings();
-}
-
-// sort timer info structs by depth first traversal order
-struct SortTimersDFS
-{
-	bool operator()(const LLFastTimer::FrameState& i1, const LLFastTimer::FrameState& i2)
-	{
-		return i1.mTimer->getFrameStateIndex() < i2.mTimer->getFrameStateIndex();
-	}
-};
-
-// sort child timers by name
-struct SortTimerByName
-{
-	bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2)
-	{
-		return i1->getName() < i2->getName();
-	}
-};
-
-//static
-void LLFastTimer::NamedTimer::buildHierarchy()
-{
-	if (sCurFrameIndex < 0 ) return;
-
-	// set up initial tree
-	{
-		for (instance_iter it = beginInstances(); it != endInstances(); ++it)
-		{
-			NamedTimer& timer = *it;
-			if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
-			
-			// bootstrap tree construction by attaching to last timer to be on stack
-			// when this timer was called
-			if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
-			{
-				timer.setParent(timer.getFrameState().mLastCaller->mTimer);
-				// no need to push up tree on first use, flag can be set spuriously
-				timer.getFrameState().mMoveUpTree = false;
-			}
-		}
-	}
-
-	// bump timers up tree if they've been flagged as being in the wrong place
-	// do this in a bottom up order to promote descendants first before promoting ancestors
-	// this preserves partial order derived from current frame's observations
-	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
-		it != end_timer_tree_bottom_up();
-		++it)
-	{
-		NamedTimer* timerp = *it;
-		// skip root timer
-		if (timerp == NamedTimerFactory::instance().getRootTimer()) continue;
-
-		if (timerp->getFrameState().mMoveUpTree)
-		{
-			// since ancestors have already been visited, reparenting won't affect tree traversal
-			//step up tree, bringing our descendants with us
-			//llinfos << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
-			//	" to child of " << timerp->getParent()->getParent()->getName() << llendl;
-			timerp->setParent(timerp->getParent()->getParent());
-			timerp->getFrameState().mMoveUpTree = false;
-
-			// don't bubble up any ancestors until descendants are done bubbling up
-			it.skipAncestors();
-		}
-	}
-
-	// sort timers by time last called, so call graph makes sense
-	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
-		it != end_timer_tree();
-		++it)
-	{
-		NamedTimer* timerp = (*it);
-		if (timerp->mNeedsSorting)
-		{
-			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
-		}
-		timerp->mNeedsSorting = false;
-	}
-}
-
-//static
-void LLFastTimer::NamedTimer::accumulateTimings()
-{
-	U32 cur_time = getCPUClockCount32();
-
-	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	LLFastTimer* cur_timer = sCurTimerData.mCurTimer;
-	// root defined by parent pointing to self
-	CurTimerData* cur_data = &sCurTimerData;
-	while(cur_timer->mLastTimerData.mCurTimer != cur_timer)
-	{
-		U32 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
-		cur_data->mChildTime = 0;
-		cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
-		cur_timer->mStartTime = cur_time;
-
-		cur_data = &cur_timer->mLastTimerData;
-		cur_data->mChildTime += cumulative_time_delta;
-
-		cur_timer = cur_timer->mLastTimerData.mCurTimer;
-	}
-
-	// traverse tree in DFS post order, or bottom up
-	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getActiveRootTimer());
-		it != end_timer_tree_bottom_up();
-		++it)
-	{
-		NamedTimer* timerp = (*it);
-		timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;