diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp
index c6ca0b542ed581e53131484b2862c887dceed166..b627110da6106e3fb5155f2eb658709d766f2e10 100755
--- a/indra/llcharacter/llkeyframewalkmotion.cpp
+++ b/indra/llcharacter/llkeyframewalkmotion.cpp
@@ -383,7 +383,7 @@ BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)
 	F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor;
 
 	// roll is critically damped interpolation between current roll and angular velocity-derived target roll
-	mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnit<F32, LLUnits::Milliseconds>(100));
+	mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnits::Milliseconds::fromValue(100));
 
 	LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f));
 	mPelvisState->setRotation(roll);
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 60c451b137aede22bc0dd63beff760a9530174af..23e27622bfcd8671a42cb0803adba5bf4bd1c758 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -386,7 +386,7 @@ void TimeBlock::dumpCurTimes()
 		U32 num_calls = last_frame_recording.getSum(timerp->callCount());
 
 		// Don't bother with really brief times, keep output concise
-		if (total_time < LLUnit<F32, LLUnits::Milliseconds>(0.1)) continue;
+		if (total_time < LLUnits::Milliseconds::fromValue(0.1f)) continue;
 
 		std::ostringstream out_str;
 		TimeBlock* parent_timerp = timerp;
@@ -397,7 +397,7 @@ void TimeBlock::dumpCurTimes()
 		}
 
 		out_str << timerp->getName() << " " 
-			<< std::setprecision(3) << total_time.getAs<LLUnits::Milliseconds>() << " ms, "
+			<< std::setprecision(3) << total_time.valueAs<LLUnits::Milliseconds>() << " ms, "
 			<< num_calls << " calls";
 
 		llinfos << out_str.str() << llendl;
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 6a0a8fcb0d9cdb91332d48bfbcf60bfae13dff04..c827996db171758478652e2cc06f2c13a7963ac2 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -173,15 +173,23 @@ class LLCopyOnWritePointer : public LLPointer<Type>
     typedef LLPointer<Type> pointer_t;
     
 	LLCopyOnWritePointer() 
+	:	mStayUnique(false)
 	{}
 
 	LLCopyOnWritePointer(Type* ptr) 
-	:	LLPointer<Type>(ptr)
+	:	LLPointer<Type>(ptr),
+		mStayUnique(false)
 	{}
 
 	LLCopyOnWritePointer(LLPointer<Type>& ptr)
-	:	LLPointer<Type>(ptr)
-	{}
+	:	LLPointer<Type>(ptr),
+		mStayUnique(false)
+	{
+		if (ptr.mForceUnique)
+		{
+			makeUnique();
+		}
+	}
 
 	Type* write()
 	{
@@ -199,6 +207,10 @@ class LLCopyOnWritePointer : public LLPointer<Type>
 
 	const Type*	operator->() const	{ return pointer_t::mPointer; }
 	const Type&	operator*() const	{ return *pointer_t::mPointer; }
+
+	void setStayUnique(bool stay) { makeUnique(); mStayUnique = stay; }
+private:
+	bool mStayUnique;
 };
 
 #endif
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 0938317eaaad9961f25602e80b7ec3339cd91f03..f1388e7935536c93e0af0629a92d59dbacdca198 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -100,14 +100,15 @@ void Recording::handleReset()
 void Recording::handleStart()
 {
 	mSamplingTimer.reset();
+	mBuffers.setStayUnique(true);
 	LLTrace::get_thread_recorder()->activate(mBuffers.write());
 }
 
 void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-	AccumulatorBufferGroup* buffers = mBuffers.write();
-	LLTrace::get_thread_recorder()->deactivate(buffers);
+	LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+	mBuffers.setStayUnique(false);
 }
 
 void Recording::handleSplitTo(Recording& other)
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 7192564c94898bf856ad319517767e2f932c5d04..d0f0328d1cccd2dd0950a3de73ac106feb71dea9 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -99,14 +99,6 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
 
 void ThreadRecorder::activate( AccumulatorBufferGroup* recording )
 {
-	active_recording_list_t::reverse_iterator it, end_it;
-	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
-		it != end_it;
-		++it)
-	{
-		llassert((*it)->mTargetRecording != recording);
-	}
-
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
 	{
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 2402cdbb95a97e4baba134b6fa6fc1ae9ab78fe9..c9bbed5574d889746b63c96c68bbdba7f745a668 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -75,17 +75,11 @@ struct LLUnit
 	}
 
 	template<typename NEW_UNIT_TYPE> 
-	STORAGE_TYPE getAs()
+	STORAGE_TYPE valueAs()
 	{
 		return LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(*this).value();
 	}
 
-	template<typename NEW_UNIT_TYPE> 
-	STORAGE_TYPE setAs(STORAGE_TYPE val)
-	{
-		*this = LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(val);
-	}
-
 	void operator += (storage_t value)
 	{
 		mValue += value;
@@ -181,6 +175,7 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
 	if (boost::is_same<T1, typename T1::base_unit_t>::value)
 	{
 		if (boost::is_same<T2, typename T2::base_unit_t>::value)
+
 		{
 			// T1 and T2 fully reduced and equal...just copy
 			out = (S2)in.value();
@@ -493,26 +488,45 @@ struct LLUnitInverseLinearOps
 	}
 };
 
-#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
-struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }}
-
-#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation)	\
-struct unit_name                                                                                \
-{                                                                                               \
-	typedef base_unit_name base_unit_t;                                                         \
-	static const char* getUnitLabel() { return unit_label; }									\
-};                                                                                              \
-	                                                                                            \
-template<typename S1, typename S2>                                                              \
-void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                \
-{                                                                                               \
-	out = (S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation).mValue;                    \
-}                                                                                               \
-                                                                                                \
-template<typename S1, typename S2>                                                              \
-void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                \
-{                                                                                               \
-	out = (S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation).mValue;             \
+#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \
+struct base_unit_name                                                                                \
+{                                                                                                    \
+	typedef base_unit_name base_unit_t;                                                              \
+	static const char* getUnitLabel() { return unit_label; }                                         \
+	template<typename T>                                                                             \
+	static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
+	template<typename STORAGE_T, typename UNIT_T>                                                    \
+	static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)              \
+	{ return LLUnit<STORAGE_T, base_unit_name>(value); }                                             \
+};                                                                                                   \
+template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, base_unit_name>& val) \
+{ s << val.value() << base_unit_name::getUnitLabel; return s; }
+
+
+#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation)	 \
+struct unit_name                                                                                 \
+{                                                                                                \
+	typedef base_unit_name base_unit_t;                                                          \
+	static const char* getUnitLabel() { return unit_label; }									 \
+	template<typename T>                                                                         \
+	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \
+	template<typename STORAGE_T, typename UNIT_T>                                                \
+	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \
+	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \
+};                                                                                               \
+template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, unit_name>& val)  \
+{ s << val.value() << unit_name::getUnitLabel; return s; }                                       \
+	                                                                                             \
+template<typename S1, typename S2>                                                               \
+void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                 \
+{                                                                                                \
+	out = (S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation).mValue;                     \
+}                                                                                                \
+                                                                                                 \
+template<typename S1, typename S2>                                                               \
+void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                 \
+{                                                                                                \
+	out = (S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation).mValue;              \
 }                                                                                               
 
 //
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 7c5cd520dad187b9dfd41bcb6d4878eeadb722af..9308f0f4e9d20962c9f6bc68ca3093d8c6b3f3d8 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1294,8 +1294,6 @@ bool LLAppViewer::mainLoop()
 	{
 		LLFastTimer _(FTM_FRAME);
 		LLTrace::TimeBlock::processTimes();
-		llassert((LLTrace::get_frame_recording().getCurRecording().update(), 
-				LLTrace::get_frame_recording().getCurRecording().getSampleCount(LLStatViewer::FPS) <= 1));
 		LLTrace::get_frame_recording().nextPeriod();
 		LLTrace::TimeBlock::logStats();
 
diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp
index e3cd83e174211bc4bcd997285adf96c93fedf899..1e1c9039fbc9316f10693fa1716ea78d5ac0f008 100755
--- a/indra/newview/llclassifiedstatsresponder.cpp
+++ b/indra/newview/llclassifiedstatsresponder.cpp
@@ -38,10 +38,8 @@
 #include "message.h"
 
 LLClassifiedStatsResponder::LLClassifiedStatsResponder(LLUUID classified_id)
-:
-mClassifiedID(classified_id)
-{
-}
+:	mClassifiedID(classified_id)
+{}
 
 /*virtual*/
 void LLClassifiedStatsResponder::result(const LLSD& content)
@@ -53,12 +51,11 @@ void LLClassifiedStatsResponder::result(const LLSD& content)
 	S32 search_map = content["search_map_clicks"].asInteger();
 	S32 search_profile = content["search_profile_clicks"].asInteger();
 
-	LLPanelClassifiedInfo::setClickThrough(
-		mClassifiedID, 
-		teleport + search_teleport, 
-		map + search_map,
-		profile + search_profile,
-		true);
+	LLPanelClassifiedInfo::setClickThrough(	mClassifiedID, 
+											teleport + search_teleport, 
+											map + search_map,
+											profile + search_profile,
+											true);
 }
 
 /*virtual*/
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index d3a97fde0e599d9e833154f29260a74ac4914300..7a5e1dcad0705f1db6fbe6fc84ace556147814ee 100755
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -1101,7 +1101,7 @@ void LLFastTimerView::drawLineGraph()
 			j--)
 		{
 			LLTrace::Recording& recording = mRecording.getPrevRecording(j);
-			LLUnit<F32, LLUnits::Seconds> time = llmax(recording.getSum(*idp), LLUnit<F64, LLUnits::Seconds>(0.000001));
+			LLUnit<F32, LLUnits::Seconds> time = llmax(recording.getSum(*idp), LLUnits::Seconds::fromValue(0.000001));
 			U32 calls = recording.getSum(idp->callCount());
 
 			if (is_hover_timer)
@@ -1126,7 +1126,7 @@ void LLFastTimerView::drawLineGraph()
 			}
 			gGL.vertex2f(x,y);
 			gGL.vertex2f(x,mGraphRect.mBottom);
-}
+		}
 		gGL.end();
 
 		if (mHoverID == idp)
@@ -1146,7 +1146,7 @@ void LLFastTimerView::drawLineGraph()
 	max_time = lerp(max_time.value(), cur_max.value(), LLSmoothInterpolation::getInterpolant(0.1f));
 	if (llabs((max_time - cur_max).value()) <= 1)
 	{
-		max_time = llmax(LLUnit<F32, LLUnits::Microseconds>(1), LLUnit<F32, LLUnits::Microseconds>(cur_max));
+		max_time = llmax(LLUnits::Microseconds::fromValue(1.f), LLUnits::Microseconds::fromValue(cur_max));
 	}
 
 	max_calls = llround(lerp((F32)max_calls, (F32) cur_max_calls, LLSmoothInterpolation::getInterpolant(0.1f)));
@@ -1423,11 +1423,11 @@ void LLFastTimerView::updateTotalTime()
 		mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME, 20);
 		break;
 	default:
-		mTotalTimeDisplay = LLUnit<F32, LLUnits::Milliseconds>(100);
+		mTotalTimeDisplay = LLUnits::Milliseconds::fromValue(100);
 		break;
 	}
 
-	mTotalTimeDisplay = LLUnit<F32, LLUnits::Milliseconds>(llceil(mTotalTimeDisplay.getAs<LLUnits::Milliseconds>() / 20.f) * 20.f);
+	mTotalTimeDisplay = LLUnits::Milliseconds::fromValue(llceil(mTotalTimeDisplay.valueAs<LLUnits::Milliseconds>() / 20.f) * 20.f);
 }
 
 void LLFastTimerView::drawBars()
diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index a4d693ec0b6907db25f2263021e63c40237f6233..342b45863a4b0bdb40aba580d7294f757fe9a441 100644
--- a/indra/newview/llscenemonitor.cpp
+++ b/indra/newview/llscenemonitor.cpp
@@ -624,7 +624,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name)
 
 		for (S32 frame = 1; frame <= frame_count; frame++)
 		{
-			os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).getAs<LLUnits::Kibibytes>();
+			os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).valueAs<LLUnits::Kibibytes>();
 		}
 
 		os << '\n';
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 4b9a950b98f7a9f57af53c84c27909596c3e6db8..0390649a1ce90baa84e461c3bacd6fd98acb375c 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -504,81 +504,85 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler
 	static const char* sStateDescs[];
 	e_state mState;
 	void setState(e_state new_state);
-	e_write_to_cache_state mWriteToCacheState;
-	LLTextureFetch* mFetcher;
+
+	e_write_to_cache_state		mWriteToCacheState;
+	LLTextureFetch*             mFetcher;
 	LLPointer<LLImageFormatted> mFormattedImage;
-	LLPointer<LLImageRaw> mRawImage;
-	LLPointer<LLImageRaw> mAuxImage;
-	FTType mFTType;
-	LLUUID mID;
-	LLHost mHost;
-	std::string mUrl;
-	U8 mType;
-	F32 mImagePriority;
-	U32 mWorkPriority;
-	F32 mRequestedPriority;
-	S32 mDesiredDiscard;
-	S32 mSimRequestedDiscard;
-	S32 mRequestedDiscard;
-	S32 mLoadedDiscard;
-	S32 mDecodedDiscard;
-	LLFrameTimer mRequestedTimer;
-	LLFrameTimer mFetchTimer;
-	LLTimer			mCacheReadTimer;
-	F32				mCacheReadTime;
-	LLTextureCache::handle_t mCacheReadHandle;
-	LLTextureCache::handle_t mCacheWriteHandle;
-	S32 mRequestedSize;
-	S32 mRequestedOffset;
-	S32 mDesiredSize;
-	S32 mFileSize;
-	S32 mCachedSize;	
-	e_request_state mSentRequest;
-	handle_t mDecodeHandle;
-	BOOL mLoaded;
-	BOOL mDecoded;
-	BOOL mWritten;
-	BOOL mNeedsAux;
-	BOOL mHaveAllData;
-	BOOL mInLocalCache;
-	BOOL mInCache;
-	bool mCanUseHTTP ;
-	bool mCanUseNET ; //can get from asset server.
-	S32 mRetryAttempt;
-	S32 mActiveCount;
-	LLCore::HttpStatus mGetStatus;
-	std::string mGetReason;
+	LLPointer<LLImageRaw>       mRawImage,
+								mAuxImage;
+	FTType                      mFTType;
+	LLUUID                      mID;
+	LLHost                      mHost;
+	std::string                 mUrl;
+	U8                          mType;
+	F32                         mImagePriority;
+	U32                         mWorkPriority;
+	F32                         mRequestedPriority;
+	S32                         mDesiredDiscard,
+								mSimRequestedDiscard,
+								mRequestedDiscard,
+								mLoadedDiscard,
+								mDecodedDiscard;
+	LLFrameTimer                mRequestedTimer,
+								mFetchTimer;
+	LLTimer						mCacheReadTimer;
+	F32							mCacheReadTime;
+	LLTextureCache::handle_t    mCacheReadHandle,
+								mCacheWriteHandle;
+	S32                         mRequestedSize,
+								mRequestedOffset,
+								mDesiredSize,
+								mFileSize,
+								mCachedSize;
+	e_request_state             mSentRequest;
+	handle_t                    mDecodeHandle;
+	BOOL                        mLoaded;
+	BOOL                        mDecoded;
+	BOOL                        mWritten;
+	BOOL                        mNeedsAux;
+	BOOL                        mHaveAllData;
+	BOOL                        mInLocalCache;
+	BOOL                        mInCache;
+	bool                        mCanUseHTTP,
+								mCanUseNET ; //can get from asset server.
+	S32                         mRetryAttempt;
+	S32                         mActiveCount;
+	LLCore::HttpStatus          mGetStatus;
+	std::string                 mGetReason;
 	
 	// Work Data
-	LLMutex mWorkMutex;
+	LLMutex						mWorkMutex;
 	struct PacketData
 	{
-		PacketData(U8* data, S32 size) { mData = data; mSize = size; }
+		PacketData(U8* data, S32 size) 
+		:	mData(data), mSize(size) 
+		{}
 		~PacketData() { clearData(); }
 		void clearData() { delete[] mData; mData = NULL; }
-		U8* mData;
-		U32 mSize;
+
+		U8*		mData;
+		U32		mSize;
 	};
-	std::vector<PacketData*> mPackets;
-	S32 mFirstPacket;
-	S32 mLastPacket;
-	U16 mTotalPackets;
-	U8 mImageCodec;
+	std::vector<PacketData*>	mPackets;
+	S32							mFirstPacket;
+	S32							mLastPacket;
+	U16							mTotalPackets;
+	U8							mImageCodec;
 
 	LLViewerAssetStats::duration_t mMetricsStartTime;
 
-	LLCore::HttpHandle		mHttpHandle;				// Handle of any active request
-	LLCore::BufferArray	*	mHttpBufferArray;			// Refcounted pointer to response data 
-	int						mHttpPolicyClass;
-	bool					mHttpActive;				// Active request to http library
-	unsigned int			mHttpReplySize;				// Actual received data size
-	unsigned int			mHttpReplyOffset;			// Actual received data offset
-	bool					mHttpHasResource;			// Counts against Fetcher's mHttpSemaphore
+	LLCore::HttpHandle			mHttpHandle;				// Handle of any active request
+	LLCore::BufferArray	*		mHttpBufferArray;			// Refcounted pointer to response data 
+	S32							mHttpPolicyClass;
+	bool						mHttpActive;				// Active request to http library
+	U32							mHttpReplySize,				// Actual received data size
+								mHttpReplyOffset;			// Actual received data offset
+	bool						mHttpHasResource;			// Counts against Fetcher's mHttpSemaphore
 
 	// State history
-	U32						mCacheReadCount;
-	U32						mCacheWriteCount;
-	U32						mResourceWaitCount;			// Requests entering WAIT_HTTP_RESOURCE2
+	U32							mCacheReadCount,
+								mCacheWriteCount,
+								mResourceWaitCount;			// Requests entering WAIT_HTTP_RESOURCE2
 };
 
 //////////////////////////////////////////////////////////////////////////////
@@ -2390,7 +2394,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	  mFetcherLocked(FALSE)
 {
 	mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
-	mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
+	mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), LLUnits::Bytes::fromValue(gSavedSettings.getU32("TextureLoggingThreshold")));
 
 	LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
 	if(LLTextureFetchDebugger::isEnabled())
@@ -3369,7 +3373,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1
 
 		if (log_to_viewer_log || log_to_sim)
 		{
-			U64 timeNow = LLTimer::getTotalTime();
+			LLUnit<U64, LLUnits::Microseconds> timeNow = LLTimer::getTotalTime();
 			mTextureInfo.setRequestSize(id, worker->mFileSize);
 			mTextureInfo.setRequestCompleteTimeAndLog(id, timeNow);
 		}
diff --git a/indra/newview/lltextureinfo.cpp b/indra/newview/lltextureinfo.cpp
index adfdbc997e288199d5e1394ae06cd09908a039eb..3ae85d56dada864daecde15729ffde6a0547a3ea 100755
--- a/indra/newview/lltextureinfo.cpp
+++ b/indra/newview/lltextureinfo.cpp
@@ -29,26 +29,28 @@
 #include "lltextureinfo.h"
 #include "lltexturestats.h"
 #include "llviewercontrol.h"
+#include "lltrace.h"
+
+static LLTrace::CountStatHandle<S32> sTextureDownloadsStarted("texture_downloads_started", "number of texture downloads initiated");
+static LLTrace::CountStatHandle<S32> sTextureDownloadsCompleted("texture_downloads_completed", "number of texture downloads completed");
+static LLTrace::CountStatHandle<LLUnit<S32, LLUnits::Bytes> > sTextureDataDownloaded("texture_data_downloaded", "amount of texture data downloaded");
+static LLTrace::CountStatHandle<LLUnit<U32, LLUnits::Milliseconds> > sTexureDownloadTime("texture_download_time", "amount of time spent fetching textures");
 
 LLTextureInfo::LLTextureInfo() : 
 	mLogTextureDownloadsToViewerLog(false),
 	mLogTextureDownloadsToSimulator(false),
-	mTotalBytes(0),
-	mTotalMilliseconds(0),
-	mTextureDownloadsStarted(0),
-	mTextureDownloadsCompleted(0),
 	mTextureDownloadProtocol("NONE"),
-	mTextureLogThreshold(100 * 1024),
-	mCurrentStatsBundleStartTime(0)
+	mTextureLogThreshold(LLUnits::Kibibytes::fromValue(100))
 {
 	mTextures.clear();
+	mRecording.start();
 }
 
-void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold)
+void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, LLUnit<U32, LLUnits::Bytes> textureLogThreshold)
 {
 	mLogTextureDownloadsToViewerLog = writeToViewerLog;
 	mLogTextureDownloadsToSimulator = sendToSim;
-	mTextureLogThreshold = textureLogThreshold;
+	mTextureLogThreshold = LLUnit<U32, LLUnits::Bytes>(textureLogThreshold);
 }
 
 LLTextureInfo::~LLTextureInfo()
@@ -94,7 +96,7 @@ void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime)
 		addRequest(id);
 	}
 	mTextures[id]->mStartTime = startTime;
-	mTextureDownloadsStarted++;
+	add(sTextureDownloadsStarted, 1);
 }
 
 void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size)
@@ -124,16 +126,19 @@ void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLReq
 	mTextures[id]->mType = type;
 }
 
-void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime)
+void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, LLUnit<U64, LLUnits::Microseconds> completeTime)
 {
 	if (!has(id))
 	{
 		addRequest(id);
 	}
-	mTextures[id]->mCompleteTime = completeTime;
+	
+	LLTextureInfoDetails& details = *mTextures[id];
+
+	details.mCompleteTime = completeTime;
 
 	std::string protocol = "NONE";
-	switch(mTextures[id]->mType)
+	switch(details.mType)
 	{
 	case LLTextureInfoDetails::REQUEST_TYPE_HTTP:
 		protocol = "HTTP";
@@ -150,24 +155,23 @@ void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeT
 
 	if (mLogTextureDownloadsToViewerLog)
 	{
-		llinfos << "texture=" << id 
-			<< " start=" << mTextures[id]->mStartTime 
-			<< " end=" << mTextures[id]->mCompleteTime
-			<< " size=" << mTextures[id]->mSize
-			<< " offset=" << mTextures[id]->mOffset
-			<< " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000
-			<< " protocol=" << protocol
-			<< llendl;
+		llinfos << "texture="   << id 
+			    << " start="    << details.mStartTime 
+			    << " end="      << details.mCompleteTime
+			    << " size="     << details.mSize
+			    << " offset="   << details.mOffset
+			    << " length="   << LLUnit<U32, LLUnits::Milliseconds>(details.mCompleteTime - details.mStartTime)
+			    << " protocol=" << protocol
+			    << llendl;
 	}
 
 	if(mLogTextureDownloadsToSimulator)
 	{
-		S32 texture_stats_upload_threshold = mTextureLogThreshold;
-		mTotalBytes += mTextures[id]->mSize;
-		mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime;
-		mTextureDownloadsCompleted++;
+		add(sTextureDataDownloaded, details.mSize);
+		add(sTexureDownloadTime, details.mCompleteTime - details.mStartTime);
+		add(sTextureDownloadsCompleted, 1);
 		mTextureDownloadProtocol = protocol;
-		if (mTotalBytes >= texture_stats_upload_threshold)
+		if (mRecording.getSum(sTextureDataDownloaded) >= mTextureLogThreshold)
 		{
 			LLSD texture_data;
 			std::stringstream startTime;
@@ -189,35 +193,33 @@ LLSD LLTextureInfo::getAverages()
 {
 	LLSD averagedTextureData;
 	S32 averageDownloadRate;
-	if(mTotalMilliseconds == 0)
+	LLUnit<U32, LLUnits::Milliseconds> download_time = mRecording.getSum(sTexureDownloadTime);
+	if(download_time == 0)
 	{
 		averageDownloadRate = 0;
 	}
 	else
 	{
-		averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds;
+		averageDownloadRate = mRecording.getSum(sTextureDataDownloaded).valueAs<LLUnits::Bits>() / download_time.valueAs<LLUnits::Seconds>();
 	}
 
-	averagedTextureData["bits_per_second"] = averageDownloadRate;
-	averagedTextureData["bytes_downloaded"] = mTotalBytes;
-	averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted;
-	averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted;
-	averagedTextureData["transport"] = mTextureDownloadProtocol;
+	averagedTextureData["bits_per_second"]             = averageDownloadRate;
+	averagedTextureData["bytes_downloaded"]            = mRecording.getSum(sTextureDataDownloaded).valueAs<LLUnits::Bytes>();
+	averagedTextureData["texture_downloads_started"]   = mRecording.getSum(sTextureDownloadsStarted);
+	averagedTextureData["texture_downloads_completed"] = mRecording.getSum(sTextureDownloadsCompleted);
+	averagedTextureData["transport"]                   = mTextureDownloadProtocol;
 
 	return averagedTextureData;
 }
 
 void LLTextureInfo::resetTextureStatistics()
 {
-	mTotalMilliseconds = 0;
-	mTotalBytes = 0;
-	mTextureDownloadsStarted = 0;
-	mTextureDownloadsCompleted = 0;
+	mRecording.restart();
 	mTextureDownloadProtocol = "NONE";
 	mCurrentStatsBundleStartTime = LLTimer::getTotalTime();
 }
 
-U32 LLTextureInfo::getRequestStartTime(const LLUUID& id)
+LLUnit<U32, LLUnits::Microseconds> LLTextureInfo::getRequestStartTime(const LLUUID& id)
 {
 	if (!has(id))
 	{
@@ -230,7 +232,7 @@ U32 LLTextureInfo::getRequestStartTime(const LLUUID& id)
 	}
 }
 
-U32 LLTextureInfo::getRequestSize(const LLUUID& id)
+LLUnit<U32, LLUnits::Bytes> LLTextureInfo::getRequestSize(const LLUUID& id)
 {
 	if (!has(id))
 	{
@@ -269,7 +271,7 @@ LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID&
 	}
 }
 
-U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id)
+LLUnit<U32, LLUnits::Microseconds> LLTextureInfo::getRequestCompleteTime(const LLUUID& id)
 {
 	if (!has(id))
 	{
diff --git a/indra/newview/lltextureinfo.h b/indra/newview/lltextureinfo.h
index 2ccbcc5fd24a87849f215df87bbab7d251e9c22e..a861a1266885f6a3700109d2fe64f57bd3e1e125 100755
--- a/indra/newview/lltextureinfo.h
+++ b/indra/newview/lltextureinfo.h
@@ -29,6 +29,7 @@
 
 #include "lluuid.h"
 #include "lltextureinfodetails.h"
+#include "lltracerecording.h"
 #include <map>
 
 class LLTextureInfo
@@ -37,18 +38,18 @@ class LLTextureInfo
 	LLTextureInfo();
 	~LLTextureInfo();
 
-	void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold);
+	void setUpLogging(bool writeToViewerLog, bool sendToSim, LLUnit<U32, LLUnits::Bytes> textureLogThreshold);
 	bool has(const LLUUID& id);
 	void setRequestStartTime(const LLUUID& id, U64 startTime);
 	void setRequestSize(const LLUUID& id, U32 size);
 	void setRequestOffset(const LLUUID& id, U32 offset);
 	void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type);
-	void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime);
-	U32 getRequestStartTime(const LLUUID& id);
-	U32 getRequestSize(const LLUUID& id);
+	void setRequestCompleteTimeAndLog(const LLUUID& id, LLUnit<U64, LLUnits::Microseconds> completeTime);
+	LLUnit<U32, LLUnits::Microseconds>getRequestStartTime(const LLUUID& id);
+	LLUnit<U32, LLUnits::Bytes> getRequestSize(const LLUUID& id);
 	U32 getRequestOffset(const LLUUID& id);
 	LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id);
-	U32 getRequestCompleteTime(const LLUUID& id);
+	LLUnit<U32, LLUnits::Microseconds> getRequestCompleteTime(const LLUUID& id);
 	void resetTextureStatistics();
 	U32 getTextureInfoMapSize();
 	LLSD getAverages();
@@ -56,19 +57,14 @@ class LLTextureInfo
 private:
 	void addRequest(const LLUUID& id);
 
-	std::map<LLUUID, LLTextureInfoDetails *> mTextures;
-
-	LLSD mAverages;
-
-	bool mLogTextureDownloadsToViewerLog;
-	bool mLogTextureDownloadsToSimulator;
-	S32 mTotalBytes;
-	S32 mTotalMilliseconds;
-	S32 mTextureDownloadsStarted;
-	S32 mTextureDownloadsCompleted;
-	std::string mTextureDownloadProtocol;
-	U32 mTextureLogThreshold; // in bytes
-	U64 mCurrentStatsBundleStartTime;
+	std::map<LLUUID, LLTextureInfoDetails *>	mTextures;
+	LLSD										mAverages;
+	bool										mLogTextureDownloadsToViewerLog,
+												mLogTextureDownloadsToSimulator;
+	std::string									mTextureDownloadProtocol;
+	LLUnit<U32, LLUnits::Bytes>					mTextureLogThreshold; 
+	LLUnit<U64, LLUnits::Microseconds>			mCurrentStatsBundleStartTime;
+	LLTrace::Recording							mRecording;
 };
 
 #endif // LL_LLTEXTUREINFO_H
diff --git a/indra/newview/lltextureinfodetails.cpp b/indra/newview/lltextureinfodetails.cpp
index 0d750db3bf0b4895770aa5a9a35387bda552b4b4..cab16eb9229b6954561089b86f342863f7e6d6ac 100755
--- a/indra/newview/lltextureinfodetails.cpp
+++ b/indra/newview/lltextureinfodetails.cpp
@@ -28,7 +28,9 @@
 
 #include "lltextureinfodetails.h"
 
-LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0)
+LLTextureInfoDetails::LLTextureInfoDetails() 
+:	mType(REQUEST_TYPE_NONE), 
+	mOffset(0)
 {
 }
 
diff --git a/indra/newview/lltextureinfodetails.h b/indra/newview/lltextureinfodetails.h
index 4a3cd290849fc20e2ab142dc70a240df92c4e817..28e957a7df33b6ef3c286df03082af73e4df46ce 100755
--- a/indra/newview/lltextureinfodetails.h
+++ b/indra/newview/lltextureinfodetails.h
@@ -28,10 +28,10 @@
 #define LL_LLTEXTUREINFODETAILS_H
 
 #include "lluuid.h"
+#include "llunit.h"
 
-class LLTextureInfoDetails
+struct LLTextureInfoDetails
 {
-public:
 	enum LLRequestType
 	{
 		REQUEST_TYPE_NONE,
@@ -39,11 +39,11 @@ class LLTextureInfoDetails
 		REQUEST_TYPE_UDP
 	};
 
-	U32 mStartTime;
-	U32 mCompleteTime;
-	U32 mOffset;
-	U32 mSize;
-	LLRequestType mType;
+	LLUnit<U32, LLUnits::Microseconds>	mStartTime,
+										mCompleteTime;
+	U32									mOffset;
+	LLUnit<U32, LLUnits::Bytes>			mSize;
+	LLRequestType						mType;
 
 	LLTextureInfoDetails();
 };
diff --git a/indra/newview/lltexturestats.cpp b/indra/newview/lltexturestats.cpp
index f820ae65df01713ab075b7ff682e3164b0af8f04..52fe78abf394f295691235d42bcabcbe3b749255 100755
--- a/indra/newview/lltexturestats.cpp
+++ b/indra/newview/lltexturestats.cpp
@@ -48,8 +48,7 @@ void send_texture_stats_to_sim(const LLSD &texture_stats)
 	texture_stats_report["stats_data"] = texture_stats;
 
 	std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats");
-	LLTextureStatsUploader tsu;
 	llinfos << "uploading texture stats data to simulator" << llendl;
-	tsu.uploadStatsToSimulator(texture_cap_url, texture_stats);
+	LLTextureStatsUploader::uploadStatsToSimulator(texture_cap_url, texture_stats);
 }
 
diff --git a/indra/newview/lltexturestatsuploader.cpp b/indra/newview/lltexturestatsuploader.cpp
index 23ba09cb9119a48fabef77c7e41c4aa232b469ff..92ec63a1133c46431d31b2c78053aa5452bc6b6a 100755
--- a/indra/newview/lltexturestatsuploader.cpp
+++ b/indra/newview/lltexturestatsuploader.cpp
@@ -30,14 +30,8 @@
 
 #include "llhttpclient.h"
 
-LLTextureStatsUploader::LLTextureStatsUploader()
-{
-}
-
-LLTextureStatsUploader::~LLTextureStatsUploader()
-{
-}
 
+// static
 void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats)
 {
 	if ( texture_cap_url != "" )
diff --git a/indra/newview/lltexturestatsuploader.h b/indra/newview/lltexturestatsuploader.h
index 6b02aeb84540c1236d3e1165547d859ae8880d2d..ac268c2516baaf7d877e734e723421263083e1c5 100755
--- a/indra/newview/lltexturestatsuploader.h
+++ b/indra/newview/lltexturestatsuploader.h
@@ -34,9 +34,7 @@
 class LLTextureStatsUploader
 {
 public:
-	LLTextureStatsUploader();
-	~LLTextureStatsUploader();
-	void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
+	static void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
 };
 
 #endif // LL_LLTEXTURESTATSUPLOADER_H
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 3d4c75cec33fa5505e5a710ff7f5dc7c143ce96c..244c150b29adbb24f72e9cfe5765a0a716e77d9c 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -291,9 +291,9 @@ F32		gAveLandCompression = 0.f,
 		gWorstWaterCompression = 0.f;
 
 LLUnit<U32, LLUnits::Bytes>		gTotalWorldData = 0, 
-						gTotalObjectData = 0, 
-						gTotalTextureData = 0;
-U32						gSimPingCount = 0;
+								gTotalObjectData = 0, 
+								gTotalTextureData = 0;
+U32								gSimPingCount = 0;
 LLUnit<U32, LLUnits::Bits>		gObjectData = 0;
 F32		gAvgSimPing = 0.f;
 LLUnit<U32, LLUnits::Bytes>		gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0};
@@ -353,7 +353,7 @@ void update_statistics()
 	}
 	else
 	{
-		sample(LLStatViewer::SIM_PING, LLUnit<F64, LLUnits::Seconds>(10));
+		sample(LLStatViewer::SIM_PING, LLUnits::Seconds::fromValue(10));
 	}
 
 	if (LLViewerStats::instance().getRecording().getSum(LLStatViewer::FPS))
@@ -403,7 +403,7 @@ void update_statistics()
 		static LLFrameTimer texture_stats_timer;
 		if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
 		{
-			gTotalTextureData = LLUnit<F64, LLUnits::Bytes>(LLViewerStats::instance().getRecording().getSum(LLStatViewer::TEXTURE_KBIT));
+			gTotalTextureData = LLViewerStats::instance().getRecording().getSum(LLStatViewer::TEXTURE_KBIT);
 			texture_stats_timer.reset();
 		}
 	}