From cc31b4ae7934010762b8aaaa7e190c74a1cd7820 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 12 Aug 2013 20:05:16 -0700
Subject: [PATCH] SH-4399 FIX: Interesting: Texture console MB Bound 0/384 and
 texture queue bounces once per second SH-4346 FIX: Interesting: some integer
 Statistics are displayed as floating point after crossing region boundary
 made llerrs/infos/etc properly variadic wrt tags LL_INFOS("A", "B", "C")
 works, for example fixed unit tests remove llsimplestat

---
 indra/llcommon/llerror.cpp                    | 507 +++++++--------
 indra/llcommon/llerror.h                      |  79 +--
 indra/llcommon/llerrorcontrol.h               |  20 +-
 indra/llcommon/lltrace.cpp                    |   2 +-
 indra/llcommon/lltrace.h                      |  10 +-
 indra/llcommon/lltraceaccumulators.h          |  12 +-
 indra/llcommon/lltracerecording.cpp           | 150 +++--
 indra/llcommon/lltracerecording.h             |  87 ++-
 indra/llcommon/llunit.h                       |  64 +-
 indra/llcommon/tests/commonmisc_test.cpp      |  10 +-
 indra/llcommon/tests/llerror_test.cpp         |  90 +--
 indra/llcommon/tests/llsdserialize_test.cpp   |   2 +-
 indra/llcommon/tests/llunits_test.cpp         |   6 +
 .../llinventory/tests/inventorymisc_test.cpp  |  12 +-
 indra/llmessage/tests/llmime_test.cpp         |   4 +-
 indra/llui/llstatbar.cpp                      | 600 ++++++++++--------
 indra/llui/llstatbar.h                        |  11 +-
 indra/llui/llxuiparser.cpp                    |  10 +-
 indra/newview/CMakeLists.txt                  |   5 -
 indra/newview/llsimplestat.h                  | 152 -----
 indra/newview/llviewerassetstats.h            |   1 -
 .../skins/default/xui/en/floater_stats.xml    |   1 -
 .../skins/default/xui/en/widgets/floater.xml  |   1 -
 indra/newview/tests/llsimplestat_test.cpp     | 580 -----------------
 indra/test/io.cpp                             |  58 +-
 indra/test/llblowfish_tut.cpp                 |   4 +-
 indra/test/lliohttpserver_tut.cpp             |   4 +-
 indra/test/llpermissions_tut.cpp              |   4 +-
 indra/test/llpipeutil.cpp                     |   4 +-
 indra/test/llsaleinfo_tut.cpp                 |   4 +-
 30 files changed, 957 insertions(+), 1537 deletions(-)
 delete mode 100755 indra/newview/llsimplestat.h
 delete mode 100755 indra/newview/tests/llsimplestat_test.cpp

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 652d0e212a3..6f128d0a209 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -51,7 +51,26 @@
 #include "lltimer.h"
 
 namespace {
-#if !LL_WINDOWS
+#if LL_WINDOWS
+	void debugger_print(const std::string& s)
+	{
+		// Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C 
+		// which works just fine under the windows debugger, but can cause users who
+		// have enabled SEHOP exception chain validation to crash due to interactions
+		// between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
+		//
+		if (IsDebuggerPresent())
+		{
+			// Need UTF16 for Unicode OutputDebugString
+			//
+			if (s.size())
+			{
+				OutputDebugString(utf8str_to_utf16str(s).c_str());
+				OutputDebugString(TEXT("\n"));
+			}
+		}
+	}
+#else
 	class RecordToSyslog : public LLError::Recorder
 	{
 	public:
@@ -98,6 +117,7 @@ namespace {
 			{
 				LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;
 			}
+			mWantsTime = true;
 		}
 		
 		~RecordToFile()
@@ -107,8 +127,6 @@ namespace {
 		
 		bool okay() { return mFile; }
 		
-		virtual bool wantsTime() { return true; }
-		
 		virtual void recordMessage(LLError::ELevel level,
 									const std::string& message)
 		{
@@ -123,10 +141,11 @@ namespace {
 	class RecordToStderr : public LLError::Recorder
 	{
 	public:
-		RecordToStderr(bool timestamp) : mTimestamp(timestamp), mUseANSI(ANSI_PROBE) { }
+		RecordToStderr(bool timestamp) : mUseANSI(ANSI_PROBE) 
+		{
+			mWantsTime = timestamp;
+		}
 
-		virtual bool wantsTime() { return mTimestamp; }
-		
 		virtual void recordMessage(LLError::ELevel level,
 					   const std::string& message)
 		{
@@ -156,7 +175,6 @@ namespace {
 		}
 	
 	private:
-		bool				mTimestamp;
 		enum ANSIState 
 		{
 			ANSI_PROBE, 
@@ -202,10 +220,13 @@ namespace {
 	class RecordToWinDebug: public LLError::Recorder
 	{
 	public:
+		RecordToWinDebug()
+		{}
+
 		virtual void recordMessage(LLError::ELevel level,
 								   const std::string& message)
 		{
-			LL_WINDOWS_OUTPUT_DEBUG(message);
+			debugger_print(message);
 		}
 	};
 #endif
@@ -217,7 +238,7 @@ namespace
 	std::string className(const std::type_info& type)
 	{
 #ifdef __GNUC__
-		// GCC: type_info::name() returns a mangled class name, must demangle
+		// GCC: type_info::name() returns a mangled class name,st demangle
 
 		static size_t abi_name_len = 100;
 		static char* abi_name_buf = (char*)malloc(abi_name_len);
@@ -394,25 +415,25 @@ namespace LLError
 	class Settings
 	{
 	public:
-		bool printLocation;
+		bool                                mPrintLocation;
 
-		LLError::ELevel defaultLevel;
-		
-		LevelMap functionLevelMap;
-		LevelMap classLevelMap;
-		LevelMap fileLevelMap;
-		LevelMap tagLevelMap;
-		std::map<std::string, unsigned int> uniqueLogMessages;
-		
-		LLError::FatalFunction crashFunction;
-		LLError::TimeFunction timeFunction;
-		
-		Recorders recorders;
-		Recorder* fileRecorder;
-		Recorder* fixedBufferRecorder;
-		std::string fileRecorderFileName;
-		
-		int shouldLogCallCounter;
+		LLError::ELevel                     mDefaultLevel;
+
+		LevelMap                            mFunctionLevelMap;
+		LevelMap                            mClassLevelMap;
+		LevelMap                            mFileLevelMap;
+		LevelMap                            mTagLevelMap;
+		std::map<std::string, unsigned int> mUniqueLogMessages;
+
+		LLError::FatalFunction              mCrashFunction;
+		LLError::TimeFunction               mTimeFunction;
+
+		Recorders                           mRecorders;
+		Recorder*                           mFileRecorder;
+		Recorder*                           mFixedBufferRecorder;
+		std::string                         mFileRecorderFileName;
+
+		int									mShouldLogCallCounter;
 		
 		static Settings& get();
 	
@@ -422,18 +443,18 @@ namespace LLError
 		
 	private:
 		Settings()
-			:	printLocation(false),
-				defaultLevel(LLError::LEVEL_DEBUG),
-				crashFunction(),
-				timeFunction(NULL),
-				fileRecorder(NULL),
-				fixedBufferRecorder(NULL),
-				shouldLogCallCounter(0)
-			{ }
+		:	mPrintLocation(false),
+			mDefaultLevel(LLError::LEVEL_DEBUG),
+			mCrashFunction(),
+			mTimeFunction(NULL),
+			mFileRecorder(NULL),
+			mFixedBufferRecorder(NULL),
+			mShouldLogCallCounter(NULL)
+		{}
 		
 		~Settings()
 		{
-			for_each(recorders.begin(), recorders.end(),
+			for_each(mRecorders.begin(), mRecorders.end(),
 					 DeletePointer());
 		}
 		
@@ -494,8 +515,8 @@ namespace LLError
 					const std::type_info& class_info, 
 					const char* function, 
 					bool printOnce,
-					const char* broadTag, 
-					const char* narrowTag)
+					const char** tags, 
+					size_t tag_count)
 	:	mLevel(level), 
 		mFile(file), 
 		mLine(line),
@@ -504,37 +525,53 @@ namespace LLError
 		mCached(false), 
 		mShouldLog(false), 
 		mPrintOnce(printOnce),
-		mBroadTag(broadTag), 
-		mNarrowTag(narrowTag)
-	{}
-
-	CallSite::CallSite(ELevel level,
-		const char* file,
-		int line,
-		const std::type_info& class_info, 
-		const char* function, 
-		bool printOnce,
-		const char* broadTag, 
-		const char* narrowTag,
-		const char*,
-		...)
-	:	mLevel(level), 
-		mFile(file), 
-		mLine(line),
-		mClassInfo(class_info), 
-		mFunction(function),
-		mCached(false), 
-		mShouldLog(false), 
-		mPrintOnce(printOnce),
-		mBroadTag(broadTag), 
-		mNarrowTag(narrowTag)
+		mTags(new const char* [tag_count]),
+		mTagCount(tag_count)
 	{
-		LL_ERRS() << "No support for more than 2 logging tags" << LL_ENDL;
+		for (int i = 0; i < tag_count; i++)
+		{
+			mTags[i] = tags[i];
+		}
+
+		switch (mLevel)
+		{
+		case LEVEL_DEBUG:		mLevelString = "DEBUG:";	break;
+		case LEVEL_INFO:		mLevelString = "INFO:";		break;
+		case LEVEL_WARN:		mLevelString = "WARNING:";	break;
+		case LEVEL_ERROR:		mLevelString = "ERROR:";	break;
+		default:				mLevelString = "XXX:";		break;
+		};
+
+		mLocationString = llformat("%s(%d) :", abbreviateFile(mFile).c_str(), mLine);
+#if LL_WINDOWS
+		// DevStudio: __FUNCTION__ already includes the full class name
+#else
+#if LL_LINUX
+		// gross, but typeid comparison seems to always fail here with gcc4.1
+		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
+#else
+		if (site.mClassInfo != typeid(NoClassInfo))
+#endif // LL_LINUX
+		{
+			mFunctionString = className(site.mClassInfo) + "::";
+		}
+#endif
+		mFunctionString += std::string(mFunction) + ":";
+		for (size_t i = 0; i < mTagCount; i++)
+		{
+			mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : " ");
+		}
 	}
 
+	CallSite::~CallSite()
+	{
+		delete []mTags;
+	}
 
 	void CallSite::invalidate()
-		{ mCached = false; }
+	{
+		mCached = false; 
+	}
 }
 
 namespace
@@ -620,25 +657,25 @@ namespace LLError
 	void setPrintLocation(bool print)
 	{
 		Settings& s = Settings::get();
-		s.printLocation = print;
+		s.mPrintLocation = print;
 	}
 
 	void setFatalFunction(const FatalFunction& f)
 	{
 		Settings& s = Settings::get();
-		s.crashFunction = f;
+		s.mCrashFunction = f;
 	}
 
     FatalFunction getFatalFunction()
     {
         Settings& s = Settings::get();
-        return s.crashFunction;
+        return s.mCrashFunction;
     }
 
 	void setTimeFunction(TimeFunction f)
 	{
 		Settings& s = Settings::get();
-		s.timeFunction = f;
+		s.mTimeFunction = f;
 	}
 
 	void setDefaultLevel(ELevel level)
@@ -646,13 +683,13 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.defaultLevel = level;
+		s.mDefaultLevel = level;
 	}
 
 	ELevel getDefaultLevel()
 	{
 		Settings& s = Settings::get();
-		return s.defaultLevel;
+		return s.mDefaultLevel;
 	}
 
 	void setFunctionLevel(const std::string& function_name, ELevel level)
@@ -660,7 +697,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.functionLevelMap[function_name] = level;
+		s.mFunctionLevelMap[function_name] = level;
 	}
 
 	void setClassLevel(const std::string& class_name, ELevel level)
@@ -668,7 +705,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.classLevelMap[class_name] = level;
+		s.mClassLevelMap[class_name] = level;
 	}
 
 	void setFileLevel(const std::string& file_name, ELevel level)
@@ -676,7 +713,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.fileLevelMap[file_name] = level;
+		s.mFileLevelMap[file_name] = level;
 	}
 
 	void setTagLevel(const std::string& tag_name, ELevel level)
@@ -684,7 +721,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.tagLevelMap[tag_name] = level;
+		s.mTagLevelMap[tag_name] = level;
 	}
 
 	LLError::ELevel decodeLevel(std::string name)
@@ -732,11 +769,11 @@ namespace LLError
 		Settings& s = Settings::get();
 		
 		g.invalidateCallSites();
-		s.functionLevelMap.clear();
-		s.classLevelMap.clear();
-		s.fileLevelMap.clear();
-		s.tagLevelMap.clear();
-		s.uniqueLogMessages.clear();
+		s.mFunctionLevelMap.clear();
+		s.mClassLevelMap.clear();
+		s.mFileLevelMap.clear();
+		s.mTagLevelMap.clear();
+		s.mUniqueLogMessages.clear();
 		
 		setPrintLocation(config["print-location"]);
 		setDefaultLevel(decodeLevel(config["default-level"]));
@@ -749,10 +786,10 @@ namespace LLError
 			
 			ELevel level = decodeLevel(entry["level"]);
 			
-			setLevels(s.functionLevelMap,	entry["functions"],	level);
-			setLevels(s.classLevelMap,		entry["classes"],	level);
-			setLevels(s.fileLevelMap,		entry["files"],		level);
-			setLevels(s.tagLevelMap,		entry["tags"],		level);
+			setLevels(s.mFunctionLevelMap,	entry["functions"],	level);
+			setLevels(s.mClassLevelMap,		entry["classes"],	level);
+			setLevels(s.mFileLevelMap,		entry["files"],		level);
+			setLevels(s.mTagLevelMap,		entry["tags"],		level);
 		}
 	}
 }
@@ -760,19 +797,44 @@ namespace LLError
 
 namespace LLError
 {
+	Recorder::Recorder()
+	:	mWantsTime(false),
+		mWantsTags(false),
+		mWantsLevel(true),
+		mWantsLocation(false),
+		mWantsFunctionName(true)
+	{}
+
 	Recorder::~Recorder()
 	{}
 
-	// virtual
 	bool Recorder::wantsTime()
 	{ 
-		return false; 
+		return mWantsTime; 
 	}
 
 	// virtual
 	bool Recorder::wantsTags()
 	{
-		return false;
+		return mWantsTags;
+	}
+
+	// virtual 
+	bool Recorder::wantsLevel() 
+	{ 
+		return mWantsLevel;
+	}
+
+	// virtual 
+	bool Recorder::wantsLocation() 
+	{ 
+		return mWantsLocation;
+	}
+
+	// virtual 
+	bool Recorder::wantsFunctionName() 
+	{ 
+		return mWantsFunctionName;
 	}
 
 	void addRecorder(Recorder* recorder)
@@ -782,7 +844,7 @@ namespace LLError
 			return;
 		}
 		Settings& s = Settings::get();
-		s.recorders.push_back(recorder);
+		s.mRecorders.push_back(recorder);
 	}
 
 	void removeRecorder(Recorder* recorder)
@@ -792,8 +854,8 @@ namespace LLError
 			return;
 		}
 		Settings& s = Settings::get();
-		s.recorders.erase(std::remove(s.recorders.begin(), s.recorders.end(), recorder),
-							s.recorders.end());
+		s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder),
+							s.mRecorders.end());
 	}
 }
 
@@ -803,10 +865,10 @@ namespace LLError
 	{
 		LLError::Settings& s = LLError::Settings::get();
 
-		removeRecorder(s.fileRecorder);
-		delete s.fileRecorder;
-		s.fileRecorder = NULL;
-		s.fileRecorderFileName.clear();
+		removeRecorder(s.mFileRecorder);
+		delete s.mFileRecorder;
+		s.mFileRecorder = NULL;
+		s.mFileRecorderFileName.clear();
 		
 		if (file_name.empty())
 		{
@@ -820,8 +882,8 @@ namespace LLError
 			return;
 		}
 
-		s.fileRecorderFileName = file_name;
-		s.fileRecorder = f;
+		s.mFileRecorderFileName = file_name;
+		s.mFileRecorder = f;
 		addRecorder(f);
 	}
 	
@@ -829,132 +891,114 @@ namespace LLError
 	{
 		LLError::Settings& s = LLError::Settings::get();
 
-		removeRecorder(s.fixedBufferRecorder);
-		delete s.fixedBufferRecorder;
-		s.fixedBufferRecorder = NULL;
+		removeRecorder(s.mFixedBufferRecorder);
+		delete s.mFixedBufferRecorder;
+		s.mFixedBufferRecorder = NULL;
 		
 		if (!fixedBuffer)
 		{
 			return;
 		}
 		
-		s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
-		addRecorder(s.fixedBufferRecorder);
+		s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
+		addRecorder(s.mFixedBufferRecorder);
 	}
 
 	std::string logFileName()
 	{
 		LLError::Settings& s = LLError::Settings::get();
-		return s.fileRecorderFileName;
+		return s.mFileRecorderFileName;
 	}
 }
 
 namespace
 {
-	void writeToRecorders(const LLError::CallSite& site, const std::string& message)
+	void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
 	{
 		LLError::ELevel level = site.mLevel;
 		LLError::Settings& s = LLError::Settings::get();
 	
-		std::string messageWithTime;
-		std::string messageWithTags;
-		std::string messageWithTagsAndTime;
-		
-		for (Recorders::const_iterator i = s.recorders.begin();
-			i != s.recorders.end();
+		for (Recorders::const_iterator i = s.mRecorders.begin();
+			i != s.mRecorders.end();
 			++i)
 		{
 			LLError::Recorder* r = *i;
-			
-			if (r->wantsTime() && s.timeFunction != NULL)
-			{
-				if (r->wantsTags())
-				{
-					if (messageWithTagsAndTime.empty())
-					{
-						messageWithTagsAndTime = s.timeFunction() + " " 
-												+ (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string())  
-												+ (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) 
-												+ message;
-					}
-
-					r->recordMessage(level, messageWithTagsAndTime);
-				}
-				else
-				{
-					if (messageWithTime.empty())
-					{
-						messageWithTime = s.timeFunction() + " " + message;
-					}
 
-					r->recordMessage(level, messageWithTime);
-				}
-			}
-			else
+			std::ostringstream message_stream;
+
+			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
 			{
-				if (r->wantsTags())
-				{
-					if (messageWithTags.empty())
-					{
-						messageWithTags = (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string())  
-										+ (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) 
-										+ message;
-					}
-
-					r->recordMessage(level, messageWithTags);
-				}
-				else
-				{
-					r->recordMessage(level, message);				
-				}
+				message_stream << site.mLocationString << " ";
 			}
-		}
-	}
-}
-
 
-/*
-Recorder formats:
+			if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
+			{
+				message_stream << s.mTimeFunction() << " ";
+			}
 
-$type = "ERROR" | "WARNING" | "ALERT" | "INFO" | "DEBUG"
-$loc = "$file($line)"
-$msg = "$loc : " if FATAL or printing loc
-		"" otherwise
-$msg += "$type: "
-$msg += contents of stringstream
+			if (show_tags && r->wantsTags())
+			{
+				message_stream << site.mTagString << " ";
+			}
 
-$time = "%Y-%m-%dT%H:%M:%SZ" if UTC
-	 or "%Y-%m-%dT%H:%M:%S %Z" if local
+			if (show_level && r->wantsLevel())
+			{
+				message_stream << site.mLevelString << " ";
+			}
+			
+			if (show_function && r->wantsFunctionName())
+			{
+				message_stream << site.mFunctionString << " ";
+			}
 
-syslog:	"$msg"
-file: "$time $msg\n"
-stderr: "$time $msg\n" except on windows, "$msg\n"
-fixedbuf: "$msg"
-winddebug: "$msg\n"
+			message_stream << message;
 
-Note: if FATAL, an additional line gets logged first, with $msg set to
-	"$loc : error"
-	
-You get:
-	llfoo.cpp(42) : error
-	llfoo.cpp(42) : ERROR: something
-	
-*/
+			r->recordMessage(level, message_stream.str());
+		}
+	}
+}
 
 namespace {
 	bool checkLevelMap(const LevelMap& map, const std::string& key,
 						LLError::ELevel& level)
 	{
+		bool stop_checking;
 		LevelMap::const_iterator i = map.find(key);
 		if (i == map.end())
 		{
-			return false;
+			return stop_checking = false;
 		}
 		
-			level = i->second;
-		return true;
+		level = i->second;
+		return stop_checking = true;
 	}
 	
+	bool checkLevelMap(	const LevelMap& map, 
+						const char *const * keys, 
+						size_t count,
+						LLError::ELevel& level)
+	{
+		bool found_level = false;
+
+		LLError::ELevel tag_level = LLError::LEVEL_NONE;
+
+		for (size_t i = 0; i < count; i++)
+		{
+			LevelMap::const_iterator it = map.find(keys[i]);
+			if (it != map.end())
+			{
+				found_level = true;
+				tag_level = llmin(tag_level, it->second);
+			}
+		}
+
+		if (found_level)
+		{
+			level = tag_level;
+		}
+		return found_level;
+	}
+
 	class LogLock
 	{
 	public:
@@ -1019,10 +1063,10 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		
-		s.shouldLogCallCounter += 1;
-		
-		std::string class_name = className(site.mClassInfo);
-		std::string function_name = functionName(site.mFunction);
+		s.mShouldLogCallCounter++;
+
+		std::string& class_name = className(site.mClassInfo);
+		std::string& function_name = functionName(site.mFunction);
 #if LL_LINUX
 		// gross, but typeid comparison seems to always fail here with gcc4.1
 		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
@@ -1033,17 +1077,18 @@ namespace LLError
 			function_name = class_name + "::" + function_name;
 		}
 
-		ELevel compareLevel = s.defaultLevel;
+		ELevel compareLevel = s.mDefaultLevel;
 
 		// The most specific match found will be used as the log level,
 		// since the computation short circuits.
 		// So, in increasing order of importance:
-		// Default < Broad Tag < File < Class < Function < Narrow Tag
-		((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false)
-		|| checkLevelMap(s.functionLevelMap, function_name, compareLevel)
-		|| checkLevelMap(s.classLevelMap, class_name, compareLevel)
-		|| checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel)
-		|| ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false);
+		// Default < Tags < File < Class < Function
+		checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel)
+		|| checkLevelMap(s.mClassLevelMap, class_name, compareLevel)
+		|| checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
+		|| (site.mTagCount > 0
+			? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel) 
+			: false);
 
 		site.mCached = true;
 		g.addCallSite(site);
@@ -1126,56 +1171,21 @@ namespace LLError
 
 		if (site.mLevel == LEVEL_ERROR)
 		{
-			std::ostringstream fatalMessage;
-			fatalMessage << abbreviateFile(site.mFile)
-						<< "(" << site.mLine << ") : error";
-			
-			writeToRecorders(site, fatalMessage.str());
+			writeToRecorders(site, "error", true, true, true, false, false);
 		}
 		
+		std::ostringstream message_stream;
 		
-		std::ostringstream prefix;
-
-		switch (site.mLevel)
-		{
-			case LEVEL_DEBUG:		prefix << "DEBUG: ";	break;
-			case LEVEL_INFO:		prefix << "INFO: ";		break;
-			case LEVEL_WARN:		prefix << "WARNING: ";	break;
-			case LEVEL_ERROR:		prefix << "ERROR: ";	break;
-			default:				prefix << "XXX: ";		break;
-		};
-		
-		if (s.printLocation)
-		{
-			prefix << abbreviateFile(site.mFile)
-					<< "(" << site.mLine << ") : ";
-		}
-		
-	#if LL_WINDOWS
-		// DevStudio: __FUNCTION__ already includes the full class name
-	#else
-                #if LL_LINUX
-		// gross, but typeid comparison seems to always fail here with gcc4.1
-		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
-                #else
-		if (site.mClassInfo != typeid(NoClassInfo))
-                #endif // LL_LINUX
-		{
-			prefix << className(site.mClassInfo) << "::";
-		}
-	#endif
-		prefix << site.mFunction << ": ";
-
 		if (site.mPrintOnce)
 		{
-			std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message);
-			if (messageIter != s.uniqueLogMessages.end())
+			std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message);
+			if (messageIter != s.mUniqueLogMessages.end())
 			{
 				messageIter->second++;
 				unsigned int num_messages = messageIter->second;
 				if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0)
 				{
-					prefix << "ONCE (" << num_messages << "th time seen): ";
+					message_stream << "ONCE (" << num_messages << "th time seen): ";
 				} 
 				else
 				{
@@ -1184,26 +1194,22 @@ namespace LLError
 			}
 			else 
 			{
-				prefix << "ONCE: ";
-				s.uniqueLogMessages[message] = 1;
+				message_stream << "ONCE: ";
+				s.mUniqueLogMessages[message] = 1;
 			}
 		}
 		
-		prefix << message;
-		message = prefix.str();
+		message_stream << message;
 		
-		writeToRecorders(site, message);
+		writeToRecorders(site, message_stream.str());
 		
-		if (site.mLevel == LEVEL_ERROR  &&  s.crashFunction)
+		if (site.mLevel == LEVEL_ERROR  &&  s.mCrashFunction)
 		{
-			s.crashFunction(message);
+			s.mCrashFunction(message_stream.str());
 		}
 	}
 }
 
-
-
-
 namespace LLError
 {
 	Settings* saveAndResetSettings()
@@ -1260,7 +1266,7 @@ namespace LLError
 	int shouldLogCallCount()
 	{
 		Settings& s = Settings::get();
-		return s.shouldLogCallCounter;
+		return s.mShouldLogCallCounter;
 	}
 
 #if LL_WINDOWS
@@ -1471,26 +1477,5 @@ namespace LLError
        sIndex = 0;
    }
 
-#if LL_WINDOWS
-	void LLOutputDebugUTF8(const std::string& s)
-	{
-		// Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C 
-		// which works just fine under the windows debugger, but can cause users who
-		// have enabled SEHOP exception chain validation to crash due to interactions
-		// between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
-		//
-		if (IsDebuggerPresent())
-		{
-			// Need UTF16 for Unicode OutputDebugString
-			//
-			if (s.size())
-			{
-				OutputDebugString(utf8str_to_utf16str(s).c_str());
-				OutputDebugString(TEXT("\n"));
-			}
-		}
-	}
-#endif
-
 }
 
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index ef25a0173c8..78106763887 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -194,14 +194,26 @@ namespace LLError
 		// Represents a specific place in the code where a message is logged
 		// This is public because it is used by the macros below.  It is not
 		// intended for public use.
-		CallSite(ELevel, const char* file, int line,
-				const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag = NULL, const char* narrowTag = NULL );
+		CallSite(ELevel level, 
+				const char* file, 
+				int line,
+				const std::type_info& class_info, 
+				const char* function, 
+				bool print_once, 
+				const char** tags, 
+				size_t tag_count);
+
+		~CallSite();
 
 #ifdef LL_LIBRARY_INCLUDE
 		bool shouldLog();
 #else // LL_LIBRARY_INCLUDE
 		bool shouldLog()
-			{ return mCached ? mShouldLog : Log::shouldLog(*this); }
+		{ 
+			return mCached 
+					? mShouldLog 
+					: Log::shouldLog(*this); 
+		}
 			// this member function needs to be in-line for efficiency
 #endif // LL_LIBRARY_INCLUDE
 		
@@ -213,20 +225,17 @@ namespace LLError
 		const int				mLine;
 		const std::type_info&   mClassInfo;
 		const char* const		mFunction;
-		const char* const		mBroadTag;
-		const char* const		mNarrowTag;
+		const char**			mTags;
+		size_t					mTagCount;
 		const bool				mPrintOnce;
-		
-		// these implement a cache of the call to shouldLog()
-		bool mCached;
-		bool mShouldLog;
+		const char*				mLevelString;
+		std::string				mLocationString,
+								mFunctionString,
+								mTagString;
+		bool					mCached,
+								mShouldLog;
 		
 		friend class Log;
-
-	private:
-		// 3 or more tags not currently supported
-		CallSite(ELevel, const char* file, int line,
-			const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag, const char* narrowTag, const char*, ...);
 	};
 	
 	
@@ -258,30 +267,21 @@ namespace LLError
        static void clear() ;
 	   static void end(std::ostringstream* _out) ;
    }; 
-
-#if LL_WINDOWS
-	void LLOutputDebugUTF8(const std::string& s);
-#endif
-
 }
 
-#if LL_WINDOWS
-	// Macro accepting a std::string for display in windows debugging console
-	#define LL_WINDOWS_OUTPUT_DEBUG(a) LLError::LLOutputDebugUTF8(a)
-#else
-	#define LL_WINDOWS_OUTPUT_DEBUG(a)
-#endif
-
 //this is cheaper than llcallstacks if no need to output other variables to call stacks. 
 #define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
-#define llcallstacks \
-	{\
+
+#define llcallstacks                                                                      \
+	{                                                                                     \
        std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \
        (*_out)
-#define llcallstacksendl \
-		LLError::End(); \
+
+#define llcallstacksendl                   \
+		LLError::End();                    \
 		LLError::LLCallStacks::end(_out) ; \
 	}
+
 #define LL_CLEAR_CALLSTACKS() LLError::LLCallStacks::clear()
 #define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print() 
 
@@ -302,13 +302,18 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 // See top of file for common usage.	
 /////////////////////////////////
 
-#define lllog(level, once, ...)																	     \
-	do {                                                                                             \
-		static LLError::CallSite _site(                                                              \
-		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, ##__VA_ARGS__ );\
-		if (LL_UNLIKELY(_site.shouldLog()))			                                                 \
-		{                                                                                            \
-			std::ostringstream* _out = LLError::Log::out();                                          \
+// this macro uses a one-shot do statement to avoid parsing errors when writing:
+// if (condition) LL_INFOS() << "True" << LLENDL; else LLINFOS() << "False" << LLENDL
+
+#define lllog(level, once, ...)																	          \
+	do {                                                                                                  \
+		const char* tags[] = {"", ##__VA_ARGS__};													      \
+		size_t tag_count = LL_ARRAY_SIZE(tags) - 1;														  \
+		static LLError::CallSite _site(                                                                   \
+		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
+		if (LL_UNLIKELY(_site.shouldLog()))			                                                      \
+		{                                                                                                 \
+			std::ostringstream* _out = LLError::Log::out();                                               \
 			(*_out)
 
 //Use this construct if you need to do computation in the middle of a
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 7c9df57115d..aab695094c7 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -136,18 +136,24 @@ namespace LLError
 	{
 		// An object that handles the actual output or error messages.
 	public:
+		Recorder();
 		virtual ~Recorder();
 
 		virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
 			// use the level for better display, not for filtering
 
-		virtual bool wantsTime(); // default returns false
-			// override and return true if the recorder wants the time string
-			// included in the text of the message
-
-		virtual bool wantsTags(); // default returns false
-			// override ands return true if the recorder wants the tags included
-			// in the text of the message
+		bool wantsTime();
+		bool wantsTags();
+		bool wantsLevel();
+		bool wantsLocation(); 
+		bool wantsFunctionName();
+
+	protected:
+		bool	mWantsTime,
+				mWantsTags,
+				mWantsLevel,
+				mWantsLocation,
+				mWantsFunctionName;
 	};
 
 	/**
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index eedf1b06f14..436ad9a0a28 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -45,7 +45,7 @@ TraceBase::TraceBase( const char* name, const char* description )
 #endif
 }
 
-const char* TraceBase::getUnitLabel()
+const char* TraceBase::getUnitLabel() const
 {
 	return "";
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 75e913a348f..1f86aadabab 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -58,7 +58,7 @@ class TraceBase
 public:
 	TraceBase(const char* name, const char* description);
 	virtual ~TraceBase() {};
-	virtual const char* getUnitLabel();
+	virtual const char* getUnitLabel() const;
 
 	const std::string& getName() const { return mName; }
 	const std::string& getDescription() const { return mDescription; }
@@ -129,7 +129,7 @@ class EventStatHandle
 	:	trace_t(name, description)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
+	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
 
 };
 
@@ -153,7 +153,7 @@ class SampleStatHandle
 	:	trace_t(name, description)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
+	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
 };
 
 template<typename T, typename VALUE_T>
@@ -176,7 +176,7 @@ class CountStatHandle
 	:	trace_t(name, description)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
+	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
 };
 
 template<typename T, typename VALUE_T>
@@ -227,7 +227,7 @@ class MemStatHandle : public TraceType<MemStatAccumulator>
 	:	trace_t(name)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return "B"; }
+	/*virtual*/ const char* getUnitLabel() const { return "B"; }
 
 	TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() 
 	{ 
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 5871dc4bea0..ef73bd30918 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -223,7 +223,6 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
-		typedef F64 mean_t;
 
 		EventAccumulator()
 		:	mSum(NaN),
@@ -269,6 +268,7 @@ namespace LLTrace
 		F64	getLastValue() const         { return mLastValue; }
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
+		F64 getSumOfSquares() const		 { return mSumOfSquares; }
 		U32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const			 { return mNumSamples > 0; }
 
@@ -289,7 +289,6 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
-		typedef F64 mean_t;
 
 		SampleAccumulator()
 		:	mSum(0),
@@ -353,6 +352,8 @@ namespace LLTrace
 		F64	getLastValue() const         { return mLastValue; }
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
+		F64 getSumOfSquares() const		 { return mSumOfSquares; }
+		LLUnitImplicit<F64, LLUnits::Seconds> getSamplingTime() { return mTotalSamplingTime; }
 		U32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const            { return mHasValue; }
 
@@ -378,7 +379,6 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
-		typedef F64 mean_t;
 
 		CountAccumulator()
 		:	mSum(0),
@@ -419,20 +419,17 @@ namespace LLTrace
 	{
 	public:
 		typedef LLUnit<F64, LLUnits::Seconds> value_t;
-		typedef LLUnit<F64, LLUnits::Seconds> mean_t;
 		typedef TimeBlockAccumulator self_t;
 
 		// fake classes that allows us to view different facets of underlying statistic
 		struct CallCountFacet 
 		{
 			typedef U32 value_t;
-			typedef F32 mean_t;
 		};
 
 		struct SelfTimeFacet
 		{
 			typedef LLUnit<F64, LLUnits::Seconds> value_t;
-			typedef LLUnit<F64, LLUnits::Seconds> mean_t;
 		};
 
 		TimeBlockAccumulator();
@@ -486,19 +483,16 @@ namespace LLTrace
 		struct AllocationCountFacet 
 		{
 			typedef U32 value_t;
-			typedef F32 mean_t;
 		};
 
 		struct DeallocationCountFacet 
 		{
 			typedef U32 value_t;
-			typedef F32 mean_t;
 		};
 
 		struct ChildMemFacet
 		{
 			typedef LLUnit<F64, LLUnits::Bytes> value_t;
-			typedef LLUnit<F64, LLUnits::Bytes> mean_t;
 		};
 
 		MemStatAccumulator()
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index a4d58d8ab13..42d97ce3144 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -242,9 +242,7 @@ F64 Recording::getSum( const TraceType<EventAccumulator>& stat )
 F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat )
 {
 	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
-	return  (sum != 0.0) 
-		? (sum / mElapsedSeconds.value())
-		: 0.0;
+	return  sum / mElapsedSeconds.value();
 }
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
@@ -522,71 +520,98 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 	getCurRecording().splitTo(other.getCurRecording());
 }
 
-
-F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64 mean = 0;
-	if (num_periods <= 0) { return mean; }
-
-	S32 total_sample_count = 0;
-
+	bool has_value = false;
+	F64 min_val = std::numeric_limits<F64>::max();
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
-
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			S32 period_sample_count = recording.getSampleCount(stat);
-			mean += recording.getMean(stat) * period_sample_count;
-			total_sample_count += period_sample_count;
+			min_val = llmin(min_val, recording.getMin(stat));
+			has_value = true;
 		}
 	}
 
-	if (total_sample_count)
+	return has_value 
+			? min_val 
+			: NaN;
+}
+
+F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+
+	bool has_value = false;
+	F64 max_val = std::numeric_limits<F64>::min();
+	for (S32 i = 1; i <= num_periods; i++)
 	{
-		mean = mean / total_sample_count;
+		Recording& recording = getPrevRecording(i);
+		if (recording.hasValue(stat))
+		{
+			max_val = llmax(max_val, recording.getMax(stat));
+			has_value = true;
+		}
 	}
-	return mean;
+
+	return has_value 
+			? max_val 
+			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+// calculates means using aggregates per period
+F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64 min_val = std::numeric_limits<F64>::max();
+	F64 mean = 0;
+	S32 valid_period_count = 0;
+
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+			mean += recording.getMean(stat);
+			valid_period_count++;
 		}
 	}
-	return min_val;
+
+	return valid_period_count 
+			? mean / (F64)valid_period_count
+			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+
+F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64 max_val = std::numeric_limits<F64>::min();
+	F64 period_mean = getPeriodMean(stat, num_periods);
+	F64 sum_of_squares = 0;
+	S32 valid_period_count = 0;
+
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			max_val = llmax(max_val, recording.getMax(stat));
+			F64 delta = recording.getMean(stat) - period_mean;
+			sum_of_squares += delta * delta;
+			valid_period_count++;
 		}
 	}
-	return max_val;
+
+	return valid_period_count
+			? sqrt((F64)sum_of_squares / (F64)valid_period_count)
+			: NaN;
 }
 
 F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
@@ -594,17 +619,21 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
+	bool has_value = false;
 	F64 min_val = std::numeric_limits<F64>::max();
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
 			min_val = llmin(min_val, recording.getMin(stat));
+			has_value = true;
 		}
 	}
-	return min_val;
+
+	return has_value 
+			? min_val 
+			: NaN;
 }
 
 F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/)
@@ -612,17 +641,21 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
+	bool has_value = false;
 	F64 max_val = std::numeric_limits<F64>::min();
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
 			max_val = llmax(max_val, recording.getMax(stat));
+			has_value = true;
 		}
 	}
-	return max_val;
+
+	return has_value 
+			? max_val 
+			: NaN;
 }
 
 
@@ -631,31 +664,48 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	LLUnit<F64, LLUnits::Seconds> total_duration(0.f);
-
+	S32 valid_period_count = 0;
 	F64 mean = 0;
-	if (num_periods <= 0) { return mean; }
 
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			LLUnit<F64, LLUnits::Seconds> recording_duration = recording.getDuration();
-			mean += recording.getMean(stat) * recording_duration.value();
-			total_duration += recording_duration;
+			mean += recording.getMean(stat);
+			valid_period_count++;
 		}
 	}
 
-	if (total_duration.value())
-	{
-		mean = mean / total_duration;
-	}
-	return mean;
+	return valid_period_count
+			? mean / F64(valid_period_count)
+			: NaN;
 }
 
+F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
+	F64 period_mean = getPeriodMean(stat, num_periods);
+	S32 valid_period_count = 0;
+	F64 sum_of_squares = 0;
+
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		Recording& recording = getPrevRecording(i);
+		if (recording.hasValue(stat))
+		{
+			F64 delta = recording.getMean(stat) - period_mean;
+			sum_of_squares += delta * delta;
+			valid_period_count++;
+		}
+	}
+
+	return valid_period_count
+			? sqrt(sum_of_squares / (F64)valid_period_count)
+			: NaN;
+}
 
 ///////////////////////////////////////////////////////////////////////
 // ExtendableRecording
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 7ee8aba874a..3722a61327c 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -210,6 +210,7 @@ namespace LLTrace
 
 		// SampleStatHandle accessors
 		bool hasValue(const TraceType<SampleAccumulator>& stat);
+
 		F64 getMin(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMin(const SampleStatHandle<T>& stat)
@@ -217,18 +218,18 @@ namespace LLTrace
 			return (T)getMin(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMean(const TraceType<SampleAccumulator>& stat);
+		F64 getMax(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
+		T getMax(const SampleStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMax(const TraceType<SampleAccumulator>& stat);
+		F64 getMean(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		T getMax(const SampleStatHandle<T>& stat)
+		typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
 		{
-			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
 		F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat);
@@ -345,8 +346,8 @@ namespace LLTrace
             size_t num_samples = 0;
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				num_samples += mRecordingPeriods[index].getSampleCount(stat);
+				Recording& recording = getPrevRecording(i);
+				num_samples += Recording.getSampleCount(stat);
 			}
 			return num_samples;
         }
@@ -365,8 +366,8 @@ namespace LLTrace
 			typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				min_val = llmin(min_val, mRecordingPeriods[index].getSum(stat));
+				Recording& recording = getPrevRecording(i)
+				min_val = llmin(min_val, recording.getSum(stat));
 			}
 			return min_val;
 		}
@@ -397,11 +398,11 @@ namespace LLTrace
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			F64 min_val = std::numeric_limits<F64>::max();
+			RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				min_val = llmin(min_val, mRecordingPeriods[index].getPerSec(stat));
+				Recording& recording = getPrevRecording(i);
+				min_val = llmin(min_val, recording.getPerSec(stat));
 			}
 			return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val;
 		}
@@ -426,8 +427,8 @@ namespace LLTrace
 			typename T::value_t max_val = std::numeric_limits<typename T::value_t>::min();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				max_val = llmax(max_val, mRecordingPeriods[index].getSum(stat));
+				Recording& recording = getPrevRecording(i);
+				max_val = llmax(max_val, recording.getSum(stat));
 			}
 			return max_val;
 		}
@@ -461,8 +462,8 @@ namespace LLTrace
 			F64 max_val = std::numeric_limits<F64>::min();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				max_val = llmax(max_val, mRecordingPeriods[index].getPerSec(stat));
+				Recording& recording = getPrevRecording(i);
+				max_val = llmax(max_val, recording.getPerSec(stat));
 			}
 			return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val;
 		}
@@ -479,24 +480,24 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename T::mean_t mean = 0;
-			if (num_periods <= 0) { return mean; }
+			typename RelatedTypes<T::value_t>::fractional_t mean = 0;
 
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				if (mRecordingPeriods[index].getDuration() > 0.f)
+				Recording& recording = getPrevRecording(i);
+				if (recording.getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[index].getSum(stat);
+					mean += recording.getSum(stat);
 				}
 			}
-			mean = mean / num_periods;
-			return mean;
+			return RelatedTypes<T::value_t>::fractional_t(num_periods
+														? mean / num_periods
+														: NaN);
 		}
 
 		template<typename T>
@@ -519,24 +520,25 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename RelatedTypes<typename T::mean_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename T::mean_t mean = 0;
-			if (num_periods <= 0) { return mean; }
+			typename RelatedTypes<T::value_t>::fractional_t mean = 0;
 
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				if (mRecordingPeriods[index].getDuration() > 0.f)
+				Recording& recording = getPrevRecording(i);
+				if (recording.getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[index].getPerSec(stat);
+					mean += recording.getPerSec(stat);
 				}
 			}
-			mean = mean / num_periods;
-			return (typename RelatedTypes<typename T::mean_t>::fractional_t)mean;
+
+			return RelatedTypes<T::value_t>::fractional_t(num_periods
+														? mean / num_periods
+														: NaN);
 		}
 
 		template<typename T>
@@ -545,6 +547,25 @@ namespace LLTrace
 			return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
 
+		//
+		// PERIODIC STANDARD DEVIATION
+		//
+
+		F64 getPeriodStandardDeviation(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+
+		template<typename T> 
+		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
+		}
+
+		F64 getPeriodStandardDeviation(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T>
+		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
+		}
+
 	private:
 		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void handleStart();
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 2e4c0de28fd..b135be48fa3 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -517,71 +517,79 @@ struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
 	static const char* getUnitLabel() { return T::getUnitLabel(); }
 };
 
-template<typename VALUE_TYPE>
+#define LL_UNIT_PROMOTE_VALUE(output_type, value) ((true ? (output_type)(1) : (value/value)) * value)
+
+template<typename INPUT_TYPE, typename OUTPUT_TYPE>
 struct LLUnitLinearOps
 {
-	typedef LLUnitLinearOps<VALUE_TYPE> self_t;
-	LLUnitLinearOps(VALUE_TYPE val) : mResult (val) {}
+	typedef LLUnitLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
+
+	LLUnitLinearOps(INPUT_TYPE val) 
+	:	mInput (val)
+	{}
 
-	operator VALUE_TYPE() const { return mResult; }
-	VALUE_TYPE mResult;
+	operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
+	INPUT_TYPE mInput;
 
 	template<typename T>
-	self_t operator * (T other)
+	output_t operator * (T other)
 	{
-		return mResult * other;
+		return mInput * other;
 	}
 
 	template<typename T>
-	self_t operator / (T other)
+	output_t operator / (T other)
 	{
-		return mResult / other;
+		return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other;
 	}
 
 	template<typename T>
-	self_t operator + (T other)
+	output_t operator + (T other)
 	{
-		return mResult + other;
+		return mInput + other;
 	}
 
 	template<typename T>
-	self_t operator - (T other)
+	output_t operator - (T other)
 	{
-		return mResult - other;
+		return mInput - other;
 	}
 };
 
-template<typename VALUE_TYPE>
+template<typename INPUT_TYPE, typename OUTPUT_TYPE>
 struct LLUnitInverseLinearOps
 {
-	typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t;
+	typedef LLUnitInverseLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
+
+	LLUnitInverseLinearOps(INPUT_TYPE val) 
+	:	mInput(val)
+	{}
 
-	LLUnitInverseLinearOps(VALUE_TYPE val) : mResult (val) {}
-	operator VALUE_TYPE() const { return mResult; }
-	VALUE_TYPE mResult;
+	operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
+	INPUT_TYPE mInput;
 
 	template<typename T>
-	self_t operator * (T other)
+	output_t operator * (T other)
 	{
-		return mResult / other;
+		return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other;
 	}
 
 	template<typename T>
-	self_t operator / (T other)
+	output_t operator / (T other)
 	{
-		return mResult * other;
+		return mInput * other;
 	}
 
 	template<typename T>
-	self_t operator + (T other)
+	output_t operator + (T other)
 	{
-		return mResult - other;
+		return mInput - other;
 	}
 
 	template<typename T>
-	self_t operator - (T other)
+	output_t operator - (T other)
 	{
-		return mResult + other;
+		return mInput + other;
 	}
 };
 
@@ -613,13 +621,13 @@ struct unit_name
 template<typename S1, typename S2>                                                                      \
 void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                        \
 {                                                                                                       \
-	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation));		\
+	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1, S2>(in.value()) conversion_operation));		\
 }                                                                                                       \
                                                                                                         \
 template<typename S1, typename S2>                                                                      \
 void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                        \
 {                                                                                                       \
-	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation));     \
+	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation));     \
 }                                                                                               
 
 //
diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp
index b115c153c17..4b3e07fa75a 100755
--- a/indra/llcommon/tests/commonmisc_test.cpp
+++ b/indra/llcommon/tests/commonmisc_test.cpp
@@ -339,7 +339,7 @@ namespace tut
 /*
 			if(actual != expected)
 			{
-				llwarns << "iteration " << i << llendl;
+				LL_WARNS() << "iteration " << i << LL_ENDL;
 				std::ostringstream e_str;
 				std::string::iterator iter = expected.begin();
 				std::string::iterator end = expected.end();
@@ -349,8 +349,8 @@ namespace tut
 				}
 				e_str << std::endl;
 				llsd_serialize_string(e_str, expected);
-				llwarns << "expected size: " << expected.size() << llendl;
-				llwarns << "expected:      " << e_str.str() << llendl;
+				LL_WARNS() << "expected size: " << expected.size() << LL_ENDL;
+				LL_WARNS() << "expected:      " << e_str.str() << LL_ENDL;
 
 				std::ostringstream a_str;
 				iter = actual.begin();
@@ -361,8 +361,8 @@ namespace tut
 				}
 				a_str << std::endl;
 				llsd_serialize_string(a_str, actual);
-				llwarns << "actual size:   " << actual.size() << llendl;
-				llwarns << "actual:      " << a_str.str() << llendl;
+				LL_WARNS() << "actual size:   " << actual.size() << LL_ENDL;
+				LL_WARNS() << "actual:      " << a_str.str() << LL_ENDL;
 			}
 */
 			ensure_equals("string value", actual, expected);
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 279a90e51b5..b28c5ba4b31 100755
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -40,7 +40,7 @@ namespace
 {
 	void test_that_error_h_includes_enough_things_to_compile_a_message()
 	{
-		llinfos << "!" << llendl;
+		LL_INFOS() << "!" << LL_ENDL;
 	}
 }
 
@@ -55,7 +55,7 @@ namespace tut
 	class TestRecorder : public LLError::Recorder
 	{
 	public:
-		TestRecorder() : mWantsTime(false) { }
+		TestRecorder() { mWantsTime = false; }
 		~TestRecorder() { LLError::removeRecorder(this); }
 
 		void recordMessage(LLError::ELevel level,
@@ -68,7 +68,6 @@ namespace tut
 		void clearMessages()		{ mMessages.clear(); }
 
 		void setWantsTime(bool t)	{ mWantsTime = t; }
-		bool wantsTime()			{ return mWantsTime; }
 
 		std::string message(int n)
 		{
@@ -82,8 +81,6 @@ namespace tut
 	private:
 		typedef std::vector<std::string> MessageVector;
 		MessageVector mMessages;
-
-		bool mWantsTime;
 	};
 
 	struct ErrorTestData
@@ -144,8 +141,8 @@ namespace tut
 	void ErrorTestObject::test<1>()
 		// basic test of output
 	{
-		llinfos << "test" << llendl;
-		llinfos << "bob" << llendl;
+		LL_INFOS() << "test" << LL_ENDL;
+		LL_INFOS() << "bob" << LL_ENDL;
 
 		ensure_message_contains(0, "test");
 		ensure_message_contains(1, "bob");
@@ -156,11 +153,11 @@ namespace
 {
 	void writeSome()
 	{
-		lldebugs << "one" << llendl;
-		llinfos << "two" << llendl;
-		llwarns << "three" << llendl;
-		llerrs << "four" << llendl;
-			// fatal messages write out and addtional "error" message
+		LL_DEBUGS() << "one" << LL_ENDL;
+		LL_INFOS() << "two" << LL_ENDL;
+		LL_WARNS() << "three" << LL_ENDL;
+		// fatal messages write out an additional "error" message
+		LL_ERRS() << "four" << LL_ENDL;
 	}
 };
 
@@ -259,19 +256,20 @@ namespace
 
 	std::string writeReturningLocation()
 	{
-		llinfos << "apple" << llendl;	int this_line = __LINE__;
+		LL_INFOS() << "apple" << LL_ENDL;	int this_line = __LINE__;
 		return locationString(this_line);
 	}
 
-	std::string writeReturningLocationAndFunction()
+	void writeReturningLocationAndFunction(std::string& location, std::string& function)
 	{
-		llinfos << "apple" << llendl;	int this_line = __LINE__;
-		return locationString(this_line) + __FUNCTION__;
+		LL_INFOS() << "apple" << LL_ENDL;	int this_line = __LINE__;
+		location = locationString(this_line);
+		function = __FUNCTION__;
 	}
 
 	std::string errorReturningLocation()
 	{
-		llerrs << "die" << llendl;	int this_line = __LINE__;
+		LL_ERRS() << "die" << LL_ENDL;	int this_line = __LINE__;
 		return locationString(this_line);
 	}
 }
@@ -306,13 +304,13 @@ namespace tut
 
 std::string logFromGlobal(bool id)
 {
-	llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl;
+	LL_INFOS() << (id ? "logFromGlobal: " : "") << "hi" << LL_ENDL;
 	return "logFromGlobal";
 }
 
 static std::string logFromStatic(bool id)
 {
-	llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl;
+	LL_INFOS() << (id ? "logFromStatic: " : "") << "hi" << LL_ENDL;
 	return "logFromStatic";
 }
 
@@ -320,7 +318,7 @@ namespace
 {
 	std::string logFromAnon(bool id)
 	{
-		llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl;
+		LL_INFOS() << (id ? "logFromAnon: " : "") << "hi" << LL_ENDL;
 		return "logFromAnon";
 	}
 }
@@ -328,7 +326,7 @@ namespace
 namespace Foo {
 	std::string logFromNamespace(bool id)
 	{
-		llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl;
+		LL_INFOS() << (id ? "Foo::logFromNamespace: " : "") << "hi" << LL_ENDL;
 		//return "Foo::logFromNamespace";
 			// there is no standard way to get the namespace name, hence
 			// we won't be testing for it
@@ -342,12 +340,12 @@ namespace
 	public:
 		std::string logFromMember(bool id)
 		{
-			llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << LL_ENDL;
 			return "ClassWithNoLogType::logFromMember";
 		}
 		static std::string logFromStatic(bool id)
 		{
-			llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
 			return "ClassWithNoLogType::logFromStatic";
 		}
 	};
@@ -357,12 +355,12 @@ namespace
 	public:
 		std::string logFromMember(bool id)
 		{
-			llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << LL_ENDL;
 			return "ClassWithLogType::logFromMember";
 		}
 		static std::string logFromStatic(bool id)
 		{
-			llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
 			return "ClassWithLogType::logFromStatic";
 		}
 	};
@@ -434,19 +432,19 @@ namespace
 {
 	std::string innerLogger()
 	{
-		llinfos << "inside" << llendl;
+		LL_INFOS() << "inside" << LL_ENDL;
 		return "moo";
 	}
 
 	std::string outerLogger()
 	{
-		llinfos << "outside(" << innerLogger() << ")" << llendl;
+		LL_INFOS() << "outside(" << innerLogger() << ")" << LL_ENDL;
 		return "bar";
 	}
 
 	void uberLogger()
 	{
-		llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl;
+		LL_INFOS() << "uber(" << outerLogger() << "," << innerLogger() << ")" << LL_ENDL;
 	}
 
 	class LogWhileLogging
@@ -454,7 +452,7 @@ namespace
 	public:
 		void print(std::ostream& out) const
 		{
-			llinfos << "logging" << llendl;
+			LL_INFOS() << "logging" << LL_ENDL;
 			out << "baz";
 		}
 	};
@@ -465,7 +463,7 @@ namespace
 	void metaLogger()
 	{
 		LogWhileLogging l;
-		llinfos << "meta(" << l << ")" << llendl;
+		LL_INFOS() << "meta(" << l << ")" << LL_ENDL;
 	}
 
 }
@@ -495,7 +493,7 @@ namespace tut
 	}
 
 	template<> template<>
-		// special handling of llerrs calls
+		// special handling of LL_ERRS() calls
 	void ErrorTestObject::test<8>()
 	{
 		LLError::setPrintLocation(false);
@@ -518,7 +516,7 @@ namespace
 
 	void ufoSighting()
 	{
-		llinfos << "ufo" << llendl;
+		LL_INFOS() << "ufo" << LL_ENDL;
 	}
 }
 
@@ -548,11 +546,13 @@ namespace tut
 		LLError::setPrintLocation(true);
 		LLError::setTimeFunction(roswell);
 		mRecorder->setWantsTime(true);
-		std::string locationAndFunction = writeReturningLocationAndFunction();
+		std::string location,
+					function;
+		writeReturningLocationAndFunction(location, function);
 
-		ensure_equals("order is time type location function message",
+		ensure_equals("order is location time type function message",
 			mRecorder->message(0),
-			roswell() + " INFO: " + locationAndFunction + ": apple");
+			location + roswell() + " INFO: " + function + ": apple");
 	}
 
 	template<> template<>
@@ -562,7 +562,7 @@ namespace tut
 		TestRecorder* altRecorder(new TestRecorder);
 		LLError::addRecorder(altRecorder);
 
-		llinfos << "boo" << llendl;
+		LL_INFOS() << "boo" << LL_ENDL;
 
 		ensure_message_contains(0, "boo");
 		ensure_equals("alt recorder count", altRecorder->countMessages(), 1);
@@ -574,7 +574,7 @@ namespace tut
 		anotherRecorder->setWantsTime(true);
 		LLError::addRecorder(anotherRecorder);
 
-		llinfos << "baz" << llendl;
+		LL_INFOS() << "baz" << LL_ENDL;
 
 		std::string when = roswell();
 
@@ -590,10 +590,10 @@ class TestAlpha
 {
 	LOG_CLASS(TestAlpha);
 public:
-	static void doDebug()	{ lldebugs << "add dice" << llendl; }
-	static void doInfo()	{ llinfos  << "any idea" << llendl; }
-	static void doWarn()	{ llwarns  << "aim west" << llendl; }
-	static void doError()	{ llerrs   << "ate eels" << llendl; }
+	static void doDebug()	{ LL_DEBUGS() << "add dice" << LL_ENDL; }
+	static void doInfo()	{ LL_INFOS()  << "any idea" << LL_ENDL; }
+	static void doWarn()	{ LL_WARNS()  << "aim west" << LL_ENDL; }
+	static void doError()	{ LL_ERRS()   << "ate eels" << LL_ENDL; }
 	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
 };
 
@@ -601,10 +601,10 @@ class TestBeta
 {
 	LOG_CLASS(TestBeta);
 public:
-	static void doDebug()	{ lldebugs << "bed down" << llendl; }
-	static void doInfo()	{ llinfos  << "buy iron" << llendl; }
-	static void doWarn()	{ llwarns  << "bad word" << llendl; }
-	static void doError()	{ llerrs   << "big easy" << llendl; }
+	static void doDebug()	{ LL_DEBUGS() << "bed down" << LL_ENDL; }
+	static void doInfo()	{ LL_INFOS()  << "buy iron" << LL_ENDL; }
+	static void doWarn()	{ LL_WARNS()  << "bad word" << LL_ENDL; }
+	static void doError()	{ LL_ERRS()   << "big easy" << LL_ENDL; }
 	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
 };
 
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 4d436e8897d..235008a5ae9 100755
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -268,7 +268,7 @@ namespace tut
 	{
 		std::stringstream stream;	
 		mFormatter->format(v, stream);
-		//llinfos << "checkRoundTrip: length " << stream.str().length() << llendl;
+		//LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
 		LLSD w;
 		mParser->reset();	// reset() call is needed since test code re-uses mParser
 		mParser->parse(stream, w, stream.str().size());
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index e631f18ad4c..ff981ca2ff7 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -53,6 +53,7 @@ namespace tut
 	template<> template<>
 	void units_object_t::test<1>()
 	{
+		LL_INFOS("test") << "Test" << LL_ENDL;
 		LLUnit<F32, Quatloos> float_quatloos;
 		ensure(float_quatloos == 0.f);
 
@@ -93,6 +94,11 @@ namespace tut
 
 		LLUnit<F32, Solari> solari(quatloos);
 		ensure(solari == 4096);
+
+		// division of integral unit
+		LLUnit<S32, Quatloos> single_quatloo(1);
+		LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
+		ensure(quarter_latinum == 0.25f);
 	}
 
 	// conversions across non-base units
diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp
index c9af7c4eac7..7b15552f246 100755
--- a/indra/llinventory/tests/inventorymisc_test.cpp
+++ b/indra/llinventory/tests/inventorymisc_test.cpp
@@ -153,7 +153,7 @@ namespace tut
 	{
 		LLPointer<LLInventoryItem> src = create_random_inventory_item();
 		LLSD sd = ll_create_sd_from_inventory_item(src);
-		//llinfos << "sd: " << *sd << llendl;
+		//LL_INFOS() << "sd: " << *sd << LL_ENDL;
 		LLPointer<LLInventoryItem> dst = new LLInventoryItem;
 		bool successful_parse = dst->fromLLSD(sd);
 		ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true);
@@ -219,7 +219,7 @@ namespace tut
 		src->setCreationDate(new_creation);
 
 		sd = ll_create_sd_from_inventory_item(src);
-		//llinfos << "sd: " << *sd << llendl;
+		//LL_INFOS() << "sd: " << *sd << LL_ENDL;
 		successful_parse = dst->fromLLSD(sd);
 		ensure_equals("13.item id::getUUID() failed", dst->getUUID(), src->getUUID());
 		ensure_equals("14.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
@@ -323,7 +323,7 @@ namespace tut
 		LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
 		if(!fp)
 		{
-			llerrs << "file could not be opened\n" << llendl;
+			LL_ERRS() << "file could not be opened\n" << LL_ENDL;
 			return;
 		}
 			
@@ -335,7 +335,7 @@ namespace tut
 		fp = LLFile::fopen("linden_file.dat","r+");
 		if(!fp)
 		{
-			llerrs << "file could not be opened\n" << llendl;
+			LL_ERRS() << "file could not be opened\n" << LL_ENDL;
 			return;
 		}
 		
@@ -460,7 +460,7 @@ namespace tut
 		LLFILE* fp = LLFile::fopen("linden_file.dat","w");
 		if(!fp)
 		{
-			llerrs << "file coudnt be opened\n" << llendl;
+			LL_ERRS() << "file coudnt be opened\n" << LL_ENDL;
 			return;
 		}
 			
@@ -472,7 +472,7 @@ namespace tut
 		fp = LLFile::fopen("linden_file.dat","r");
 		if(!fp)
 		{
-			llerrs << "file coudnt be opened\n" << llendl;
+			LL_ERRS() << "file coudnt be opened\n" << LL_ENDL;
 			return;
 		}
 		
diff --git a/indra/llmessage/tests/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp
index aed5c4589cb..ea48561ae9c 100755
--- a/indra/llmessage/tests/llmime_test.cpp
+++ b/indra/llmessage/tests/llmime_test.cpp
@@ -83,8 +83,8 @@ namespace tut
 		headers["Content-Length"] = MULTI_CONTENT_LENGTH;
 		headers["Content-Type"] = MULTI_CONTENT_TYPE;
 		LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
-		llinfos << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
-			<< llendl;
+		LL_INFOS() << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
+			<< LL_ENDL;
 
 
 		const S32 META_CONTENT_LENGTH = 700;
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
index ee73cfa40da..900f81992c1 100755
--- a/indra/llui/llstatbar.cpp
+++ b/indra/llui/llstatbar.cpp
@@ -160,7 +160,8 @@ LLStatBar::LLStatBar(const Params& p)
 	mOrientation(p.orientation),
 	mAutoScaleMax(!p.bar_max.isProvided()),
 	mAutoScaleMin(!p.bar_min.isProvided()),
-	mTickValue(p.tick_spacing)
+	mTickValue(p.tick_spacing),
+	mLastDisplayValue(0.f)
 {
 	// tick value will be automatically calculated later
 	if (!p.tick_spacing.isProvided() && p.bar_min.isProvided() && p.bar_max.isProvided())
@@ -219,323 +220,281 @@ BOOL LLStatBar::handleMouseDown(S32 x, S32 y, MASK mask)
 	return TRUE;
 }
 
-void LLStatBar::draw()
+template<typename T>
+S32 calc_num_rapid_changes(LLTrace::PeriodicRecording& periodic_recording, const T& stat, const LLUnit<F32, LLUnits::Seconds> time_period)
 {
-	F32 current		= 0, 
-		min			= 0, 
-		max			= 0,
-		mean		= 0;
+	LLUnit<F32, LLUnits::Seconds>	elapsed_time,
+									time_since_value_changed;
+	S32 num_rapid_changes = 0;
+	const LLUnit<F32, LLUnits::Seconds>	RAPID_CHANGE_THRESHOLD = LLUnits::Seconds::fromValue(0.3f);
 
-    bool show_data = false;
-    
-	LLLocalClipRect _(getLocalRect());
-	LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+	F64 last_value = periodic_recording.getPrevRecording(1).getLastValue(stat);
+	for (S32 i = 2; i < periodic_recording.getNumRecordedPeriods(); i++)
+	{
+		LLTrace::Recording& recording = periodic_recording.getPrevRecording(i);
+		F64 cur_value = recording.getLastValue(stat);
 
-	S32 num_frames = mDisplayHistory ? mNumHistoryFrames : mNumShortHistoryFrames;
+		if (last_value != cur_value)
+		{
+			if (time_since_value_changed < RAPID_CHANGE_THRESHOLD) num_rapid_changes++;
+			time_since_value_changed = 0;	
+		}
+		last_value = cur_value;
 
-	std::string unit_label;
-	if (mCountFloatp)
-	{
-		LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording(); 
-		unit_label = mUnitLabel.empty() ? mCountFloatp->getUnitLabel() : mUnitLabel;
-		unit_label += "/s";
-		current = last_frame_recording.getPerSec(*mCountFloatp);
-		min     = frame_recording.getPeriodMinPerSec(*mCountFloatp, num_frames);
-		max     = frame_recording.getPeriodMaxPerSec(*mCountFloatp, num_frames);
-		mean    = frame_recording.getPeriodMeanPerSec(*mCountFloatp, num_frames);
-
-		// always show count-style data
-		show_data = true;
+		elapsed_time += recording.getDuration();
+		if (elapsed_time > time_period) break;
 	}
-	else if (mEventFloatp)
+
+	return num_rapid_changes;
+}
+
+S32 calc_num_rapid_changes(LLTrace::PeriodicRecording& periodic_recording, const LLTrace::TraceType<LLTrace::CountAccumulator>& stat, const LLUnit<F32, LLUnits::Seconds> time_period)
+{
+	LLUnit<F32, LLUnits::Seconds>	elapsed_time,
+		time_since_value_changed;
+	S32 num_rapid_changes = 0;
+	const LLUnit<F32, LLUnits::Seconds>	RAPID_CHANGE_THRESHOLD = LLUnits::Seconds::fromValue(0.3f);
+
+	F64 last_value = periodic_recording.getPrevRecording(1).getSum(stat);
+	for (S32 i = 1; i < periodic_recording.getNumRecordedPeriods(); i++)
 	{
-		LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
-		unit_label = mUnitLabel.empty() ? mEventFloatp->getUnitLabel() : mUnitLabel;
+		LLTrace::Recording& recording = periodic_recording.getPrevRecording(i);
+		F64 cur_value = recording.getSum(stat);
 
-		// only show data if there is an event in the relevant time period
-		current = last_frame_recording.getMean(*mEventFloatp);
-		min     = frame_recording.getPeriodMin(*mEventFloatp, num_frames);
-		max     = frame_recording.getPeriodMax(*mEventFloatp, num_frames);
-		mean    = frame_recording.getPeriodMean(*mEventFloatp, num_frames);
+		if (last_value != cur_value)
+		{
+			if (time_since_value_changed < RAPID_CHANGE_THRESHOLD) num_rapid_changes++;
+			time_since_value_changed = 0;	
+		}
+		last_value = cur_value;
 
-		show_data = frame_recording.getSampleCount(*mEventFloatp, num_frames) != 0;
+		elapsed_time += recording.getDuration();
+		if (elapsed_time > time_period) break;
 	}
-	else if (mSampleFloatp)
-	{
 
-		LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
-		unit_label = mUnitLabel.empty() ? mSampleFloatp->getUnitLabel() : mUnitLabel;
+	return num_rapid_changes;
+}
 
-		current = last_frame_recording.getMean(*mSampleFloatp);
-		min     = frame_recording.getPeriodMin(*mSampleFloatp, num_frames);
-		max     = frame_recording.getPeriodMax(*mSampleFloatp, num_frames);
-		mean    = frame_recording.getPeriodMean(*mSampleFloatp, num_frames);
+void LLStatBar::draw()
+{
+	LLLocalClipRect _(getLocalRect());
 
-		// always show sample data if we've ever grabbed any samples
-		show_data = last_frame_recording.hasValue(*mSampleFloatp);
-	}
+	LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording(); 
 
-	S32 bar_top, bar_left, bar_right, bar_bottom;
-	if (mOrientation == HORIZONTAL)
+	std::string unit_label;
+	F32 current			= 0, 
+		min				= 0, 
+		max				= 0,
+		mean			= 0,
+		display_value	= 0;
+	S32 num_frames		= mDisplayHistory 
+						? mNumHistoryFrames 
+						: mNumShortHistoryFrames;
+	S32 num_rapid_changes = 0;
+
+	const S32 MAX_RAPID_CHANGES = 6;
+	const F32 MIN_VALUE_UPDATE_TIME = 1.f / 4.f;
+	const LLUnit<F32, LLUnits::Seconds> CHANGE_WINDOW = LLUnits::Seconds::fromValue(2.f);
+
+	if (mCountFloatp)
 	{
-		bar_top    = llmax(5, getRect().getHeight() - 15); 
-		bar_left   = 0;
-		bar_right  = getRect().getWidth() - 40;
-		bar_bottom = llmin(bar_top - 5, 0);
+		const LLTrace::TraceType<LLTrace::CountAccumulator>& count_stat = *mCountFloatp;
+
+		unit_label = mUnitLabel.empty() ? (std::string(count_stat.getUnitLabel()) + "/s") : mUnitLabel;
+		current = last_frame_recording.getPerSec(count_stat);
+		min     = frame_recording.getPeriodMinPerSec(count_stat, num_frames);
+		max     = frame_recording.getPeriodMaxPerSec(count_stat, num_frames);
+		mean    = frame_recording.getPeriodMeanPerSec(count_stat, num_frames);
+		num_rapid_changes = calc_num_rapid_changes(frame_recording, count_stat, CHANGE_WINDOW);
 	}
-	else // VERTICAL
+	else if (mEventFloatp)
 	{
-		bar_top    = llmax(5, getRect().getHeight() - 15); 
-		bar_left   = 0;
-		bar_right  = getRect().getWidth();
-		bar_bottom = llmin(bar_top - 5, 20);
-	}
-	const S32 tick_length = 4;
-	const S32 tick_width = 1;
+		const LLTrace::TraceType<LLTrace::EventAccumulator>& event_stat = *mEventFloatp;
 
-	if ((mAutoScaleMax && max >= mCurMaxBar)|| (mAutoScaleMin && min <= mCurMinBar))
-	{
-		F32 range_min = mAutoScaleMin ? llmin(mMinBar, min) : mMinBar;
-		F32 range_max = mAutoScaleMax ? llmax(mMaxBar, max) : mMaxBar;
-		F32 tick_value = 0.f;
-		calc_auto_scale_range(range_min, range_max, tick_value);
-		if (mAutoScaleMin) { mMinBar = range_min; }
-		if (mAutoScaleMax) { mMaxBar = range_max; }
-		if (mAutoScaleMin && mAutoScaleMax)
-		{
-			mTickValue = tick_value;
-		}
-		else
-		{
-			mTickValue = calc_tick_value(mMinBar, mMaxBar);
-		}
+		unit_label = mUnitLabel.empty() ? event_stat.getUnitLabel() : mUnitLabel;
+
+		current = last_frame_recording.getLastValue(event_stat);
+		min     = frame_recording.getPeriodMin(event_stat, num_frames);
+		max     = frame_recording.getPeriodMax(event_stat, num_frames);
+		mean    = frame_recording.getPeriodMean(event_stat, num_frames);
+		num_rapid_changes = calc_num_rapid_changes(frame_recording, event_stat, CHANGE_WINDOW);
 	}
+	else if (mSampleFloatp)
+	{
+		const LLTrace::TraceType<LLTrace::SampleAccumulator>& sample_stat = *mSampleFloatp;
 
-	mCurMaxBar = LLSmoothInterpolation::lerp(mCurMaxBar, mMaxBar, 0.05f);
-	mCurMinBar = LLSmoothInterpolation::lerp(mCurMinBar, mMinBar, 0.05f);
+		unit_label = mUnitLabel.empty() ? sample_stat.getUnitLabel() : mUnitLabel;
 
-	F32 value_scale;
-	if (mCurMaxBar == mCurMinBar)
-	{
-		value_scale = 0.f;
+		current = last_frame_recording.getLastValue(sample_stat);
+		min     = frame_recording.getPeriodMin(sample_stat, num_frames);
+		max     = frame_recording.getPeriodMax(sample_stat, num_frames);
+		mean    = frame_recording.getPeriodMean(sample_stat, num_frames);
+		num_rapid_changes = calc_num_rapid_changes(frame_recording, sample_stat, CHANGE_WINDOW);
 	}
-	else
+
+	if (mLastDisplayValueTimer.getElapsedTimeF32() > MIN_VALUE_UPDATE_TIME)
 	{
-		value_scale = (mOrientation == HORIZONTAL) 
-					? (bar_top - bar_bottom)/(mCurMaxBar - mCurMinBar)
-					: (bar_right - bar_left)/(mCurMaxBar - mCurMinBar);
+		mLastDisplayValueTimer.reset();
+		display_value	= (num_rapid_changes > MAX_RAPID_CHANGES)
+			? mean
+			: current;
+		mLastDisplayValue = display_value;
 	}
-
-	LLFontGL::getFontMonospace()->renderUTF8(mLabel, 0, 0, getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, 1.f),
-											 LLFontGL::LEFT, LLFontGL::TOP);
-	
-	S32 decimal_digits = mDecimalDigits;
-	if (is_approx_equal((F32)(S32)mean, mean))
+	else
 	{
-		decimal_digits = 0;
+		display_value = mLastDisplayValue;
 	}
-	std::string value_str = show_data 
-                            ? llformat("%10.*f %s", decimal_digits, mean, unit_label.c_str())
-                            : "n/a";
 
-	// Draw the current value.
+	LLRect bar_rect;
 	if (mOrientation == HORIZONTAL)
 	{
-		LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, bar_right, getRect().getHeight(), 
-			LLColor4(1.f, 1.f, 1.f, 0.5f),
-			LLFontGL::RIGHT, LLFontGL::TOP);
+		bar_rect.mTop	 = llmax(5, getRect().getHeight() - 15); 
+		bar_rect.mLeft   = 0;
+		bar_rect.mRight  = getRect().getWidth() - 40;
+		bar_rect.mBottom = llmin(bar_rect.mTop - 5, 0);
 	}
-	else
+	else // VERTICAL
 	{
-		LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, bar_right, getRect().getHeight(), 
-			LLColor4(1.f, 1.f, 1.f, 0.5f),
-			LLFontGL::RIGHT, LLFontGL::TOP);
+		bar_rect.mTop    = llmax(5, getRect().getHeight() - 15); 
+		bar_rect.mLeft   = 0;
+		bar_rect.mRight  = getRect().getWidth();
+		bar_rect.mBottom = llmin(bar_rect.mTop - 5, 20);
 	}
 
+	mCurMaxBar = LLSmoothInterpolation::lerp(mCurMaxBar, mMaxBar, 0.05f);
+	mCurMinBar = LLSmoothInterpolation::lerp(mCurMinBar, mMinBar, 0.05f);
+
+	drawLabelAndValue(display_value, unit_label, bar_rect);
+
 	if (mDisplayBar
         && (mCountFloatp || mEventFloatp || mSampleFloatp))
 	{
 		// Draw the tick marks.
 		LLGLSUIDefault gls_ui;
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		S32 last_tick = 0;
-		S32 last_label = 0;
-		const S32 MIN_TICK_SPACING  = mOrientation == HORIZONTAL ? 20 : 30;
-		const S32 MIN_LABEL_SPACING = mOrientation == HORIZONTAL ? 30 : 60;
-		// start counting from actual min, not current, animating min, so that ticks don't float between numbers
-		// ensure ticks always hit 0
-		if (mTickValue > 0.f)
+
+		F32 value_scale;
+		if (mCurMaxBar == mCurMinBar)
+		{
+			value_scale = 0.f;
+		}
+		else
 		{
-			F32 start = mCurMinBar < 0.f
-				? llceil(-mCurMinBar / mTickValue) * -mTickValue
-				: 0.f;
-			for (F32 tick_value = start; ;tick_value += mTickValue)
+			value_scale = (mOrientation == HORIZONTAL) 
+				? (bar_rect.getHeight())/(mCurMaxBar - mCurMinBar)
+				: (bar_rect.getWidth())/(mCurMaxBar - mCurMinBar);
+		}
+
+		drawTicks(min, max, value_scale, bar_rect);
+
+		// draw background bar.
+		gl_rect_2d(bar_rect.mLeft, bar_rect.mTop, bar_rect.mRight, bar_rect.mBottom, LLColor4(0.f, 0.f, 0.f, 0.25f));
+
+		// draw values
+		if (!llisnan(display_value) && frame_recording.getNumRecordedPeriods() != 0)
+		{
+			// draw min and max
+			S32 begin = (S32) ((min - mCurMinBar) * value_scale);
+
+			if (begin < 0)
 			{
-				const S32 begin = llfloor((tick_value - mCurMinBar)*value_scale);
-				const S32 end = begin + tick_width;
-				if (begin - last_tick < MIN_TICK_SPACING)
-				{
-					continue;
-				}
-				last_tick = begin;
+				begin = 0;
+			}
 
-				S32 decimal_digits = mDecimalDigits;
-				if (is_approx_equal((F32)(S32)tick_value, tick_value))
-				{
-					decimal_digits = 0;
-				}
-				std::string tick_string = llformat("%10.*f", decimal_digits, tick_value);
+			S32 end = (S32) ((max - mCurMinBar) * value_scale);
+			if (mOrientation == HORIZONTAL)
+			{
+				gl_rect_2d(bar_rect.mLeft, end, bar_rect.mRight, begin, LLColor4(1.f, 0.f, 0.f, 0.25f));
+			}
+			else // VERTICAL
+			{
+				gl_rect_2d(begin, bar_rect.mTop, end, bar_rect.mBottom, LLColor4(1.f, 0.f, 0.f, 0.25f));
+			}
 
-				if (mOrientation == HORIZONTAL)
+			F32 span = (mOrientation == HORIZONTAL)
+					? (bar_rect.getWidth())
+					: (bar_rect.getHeight());
+
+			if (mDisplayHistory && (mCountFloatp || mEventFloatp || mSampleFloatp))
+			{
+				const S32 num_values = frame_recording.getNumRecordedPeriods() - 1;
+				F32 value = 0;
+				S32 i;
+				gGL.color4f( 1.f, 0.f, 0.f, 1.f );
+				gGL.begin( LLRender::QUADS );
+				const S32 max_frame = llmin(num_frames, num_values);
+				U32 num_samples = 0;
+				for (i = 1; i <= max_frame; i++)
 				{
-					if (begin - last_label > MIN_LABEL_SPACING)
+					F32 offset = ((F32)i / (F32)num_frames) * span;
+					LLTrace::Recording& recording = frame_recording.getPrevRecording(i);
+
+					if (mCountFloatp)
 					{
-						gl_rect_2d(bar_left, end, bar_right - tick_length, begin, LLColor4(1.f, 1.f, 1.f, 0.25f));
-						LLFontGL::getFontMonospace()->renderUTF8(tick_string, 0, bar_right, begin,
-							LLColor4(1.f, 1.f, 1.f, 0.5f),
-							LLFontGL::LEFT, LLFontGL::VCENTER);
-						last_label = begin;
+						value       = recording.getPerSec(*mCountFloatp);
+						num_samples = recording.getSampleCount(*mCountFloatp);
 					}
-					else
+					else if (mEventFloatp)
 					{
-						gl_rect_2d(bar_left, end, bar_right - tick_length/2, begin, LLColor4(1.f, 1.f, 1.f, 0.1f));
+						value       = recording.getMean(*mEventFloatp);
+						num_samples = recording.getSampleCount(*mEventFloatp);
 					}
-				}
-				else
-				{
-					if (begin - last_label > MIN_LABEL_SPACING)
+					else if (mSampleFloatp)
+					{
+						value       = recording.getMean(*mSampleFloatp);
+						num_samples = recording.getSampleCount(*mSampleFloatp);
+					}
+                    
+					if (!num_samples) continue;
+
+					F32 begin = (value  - mCurMinBar) * value_scale;
+					if (mOrientation == HORIZONTAL)
 					{
-						gl_rect_2d(begin, bar_top, end, bar_bottom - tick_length, LLColor4(1.f, 1.f, 1.f, 0.25f));
-						LLFontGL::getFontMonospace()->renderUTF8(tick_string, 0, begin - 1, bar_bottom - tick_length,
-							LLColor4(1.f, 1.f, 1.f, 0.5f),
-							LLFontGL::RIGHT, LLFontGL::TOP);
-						last_label = begin;
+						gGL.vertex2f((F32)bar_rect.mRight - offset, begin + 1);
+						gGL.vertex2f((F32)bar_rect.mRight - offset, begin);
+						gGL.vertex2f((F32)bar_rect.mRight - offset - 1, begin);
+						gGL.vertex2f((F32)bar_rect.mRight - offset - 1, begin + 1);
 					}
 					else
 					{
-						gl_rect_2d(begin, bar_top, end, bar_bottom - tick_length/2, LLColor4(1.f, 1.f, 1.f, 0.1f));
+						gGL.vertex2f(begin, (F32)bar_rect.mBottom + offset + 1);
+						gGL.vertex2f(begin, (F32)bar_rect.mBottom + offset);
+						gGL.vertex2f(begin + 1, (F32)bar_rect.mBottom + offset);
+						gGL.vertex2f(begin + 1, (F32)bar_rect.mBottom + offset + 1 );
 					}
 				}
-				// always draw one tick value past end, so we can see part of the text, if possible
-				if (tick_value > mCurMaxBar)
+				gGL.end();
+			}
+			else
+			{
+				S32 begin = (S32) ((current - mCurMinBar) * value_scale) - 1;
+				S32 end = (S32) ((current - mCurMinBar) * value_scale) + 1;
+				// draw current
+				if (mOrientation == HORIZONTAL)
+				{
+					gl_rect_2d(bar_rect.mLeft, end, bar_rect.mRight, begin, LLColor4(1.f, 0.f, 0.f, 1.f));
+				}
+				else
 				{
-					break;
+					gl_rect_2d(begin, bar_rect.mTop, end, bar_rect.mBottom, LLColor4(1.f, 0.f, 0.f, 1.f));
 				}
 			}
-		}
-
-		// draw background bar.
-		gl_rect_2d(bar_left, bar_top, bar_right, bar_bottom, LLColor4(0.f, 0.f, 0.f, 0.25f));
-
-		if (frame_recording.getNumRecordedPeriods() == 0)
-		{
-			// No data, don't draw anything...
-			return;
-		}
 
-		// draw min and max
-		S32 begin = (S32) ((min - mCurMinBar) * value_scale);
-
-		if (begin < 0)
-		{
-			begin = 0;
-		}
-
-		S32 end = (S32) ((max - mCurMinBar) * value_scale);
-		if (mOrientation == HORIZONTAL)
-		{
-			gl_rect_2d(bar_left, end, bar_right, begin, LLColor4(1.f, 0.f, 0.f, 0.25f));
-		}
-		else // VERTICAL
-		{
-			gl_rect_2d(begin, bar_top, end, bar_bottom, LLColor4(1.f, 0.f, 0.f, 0.25f));
+			// draw mean bar
+			{
+				const S32 begin = (S32) ((mean - mCurMinBar) * value_scale) - 1;
+				const S32 end = (S32) ((mean - mCurMinBar) * value_scale) + 1;
+				if (mOrientation == HORIZONTAL)
+				{
+					gl_rect_2d(bar_rect.mLeft - 2, begin, bar_rect.mRight + 2, end, LLColor4(0.f, 1.f, 0.f, 1.f));
+				}
+				else
+				{
+					gl_rect_2d(begin, bar_rect.mTop + 2, end, bar_rect.mBottom - 2, LLColor4(0.f, 1.f, 0.f, 1.f));
+				}
+			}
 		}
-
-        if (show_data)
-        {
-            F32 span = (mOrientation == HORIZONTAL)
-					? (bar_right - bar_left)
-					: (bar_top - bar_bottom);
-
-            if (mDisplayHistory && (mCountFloatp || mEventFloatp || mSampleFloatp))
-            {
-                const S32 num_values = frame_recording.getNumRecordedPeriods() - 1;
-                F32 value = 0;
-                S32 i;
-                gGL.color4f( 1.f, 0.f, 0.f, 1.f );
-                gGL.begin( LLRender::QUADS );
-                const S32 max_frame = llmin(num_frames, num_values);
-                U32 num_samples = 0;
-                for (i = 1; i <= max_frame; i++)
-                {
-                    F32 offset = ((F32)i / (F32)num_frames) * span;
-                    LLTrace::Recording& recording = frame_recording.getPrevRecording(i);
-
-                    if (mCountFloatp)
-                    {
-                        value       = recording.getPerSec(*mCountFloatp);
-                        num_samples = recording.getSampleCount(*mCountFloatp);
-                    }
-                    else if (mEventFloatp)
-                    {
-                        value       = recording.getMean(*mEventFloatp);
-                        num_samples = recording.getSampleCount(*mEventFloatp);
-                    }
-                    else if (mSampleFloatp)
-                    {
-                        value       = recording.getMean(*mSampleFloatp);
-                        num_samples = recording.getSampleCount(*mSampleFloatp);
-                    }
-                    
-                    if (!num_samples) continue;
-
-                    F32 begin = (value  - mCurMinBar) * value_scale;
-                    if (mOrientation == HORIZONTAL)
-                    {
-                        gGL.vertex2f((F32)bar_right - offset, begin + 1);
-                        gGL.vertex2f((F32)bar_right - offset, begin);
-                        gGL.vertex2f((F32)bar_right - offset - 1, begin);
-                        gGL.vertex2f((F32)bar_right - offset - 1, begin + 1);
-                    }
-                    else
-                    {
-                        gGL.vertex2f(begin, (F32)bar_bottom + offset + 1);
-                        gGL.vertex2f(begin, (F32)bar_bottom + offset);
-                        gGL.vertex2f(begin + 1, (F32)bar_bottom + offset);
-                        gGL.vertex2f(begin + 1, (F32)bar_bottom + offset + 1 );
-                    }
-                }
-                gGL.end();
-            }
-            else
-            {
-                S32 begin = (S32) ((current - mCurMinBar) * value_scale) - 1;
-                S32 end = (S32) ((current - mCurMinBar) * value_scale) + 1;
-                // draw current
-                if (mOrientation == HORIZONTAL)
-                {
-                    gl_rect_2d(bar_left, end, bar_right, begin, LLColor4(1.f, 0.f, 0.f, 1.f));
-                }
-                else
-                {
-                    gl_rect_2d(begin, bar_top, end, bar_bottom, LLColor4(1.f, 0.f, 0.f, 1.f));
-                }
-            }
-
-            // draw mean bar
-            {
-                const S32 begin = (S32) ((mean - mCurMinBar) * value_scale) - 1;
-                const S32 end = (S32) ((mean - mCurMinBar) * value_scale) + 1;
-                if (mOrientation == HORIZONTAL)
-                {
-                    gl_rect_2d(bar_left - 2, begin, bar_right + 2, end, LLColor4(0.f, 1.f, 0.f, 1.f));
-                }
-                else
-                {
-                    gl_rect_2d(begin, bar_top + 2, end, bar_bottom - 2, LLColor4(0.f, 1.f, 0.f, 1.f));
-                }
-            }
-        }
 	}
 	
 	LLView::draw();
@@ -578,3 +537,124 @@ LLRect LLStatBar::getRequiredRect()
 	return rect;
 }
 
+void LLStatBar::drawLabelAndValue( F32 value, std::string &label, LLRect &bar_rect )
+{
+	LLFontGL::getFontMonospace()->renderUTF8(mLabel, 0, 0, getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, 1.f),
+		LLFontGL::LEFT, LLFontGL::TOP);
+
+	S32 decimal_digits = mDecimalDigits;
+	if (is_approx_equal((F32)(S32)value, value))
+	{
+		decimal_digits = 0;
+	}
+	std::string value_str	= !llisnan(value)
+							? llformat("%10.*f %s", decimal_digits, value, label.c_str())
+							: "n/a";
+
+	// Draw the current value.
+	if (mOrientation == HORIZONTAL)
+	{
+		LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, bar_rect.mRight, getRect().getHeight(), 
+			LLColor4(1.f, 1.f, 1.f, 0.5f),
+			LLFontGL::RIGHT, LLFontGL::TOP);
+	}
+	else
+	{
+		LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, bar_rect.mRight, getRect().getHeight(), 
+			LLColor4(1.f, 1.f, 1.f, 0.5f),
+			LLFontGL::RIGHT, LLFontGL::TOP);
+	}
+}
+
+void LLStatBar::drawTicks( F32 min, F32 max, F32 value_scale, LLRect &bar_rect )
+{
+	if ((mAutoScaleMax && max >= mCurMaxBar)|| (mAutoScaleMin && min <= mCurMinBar))
+	{
+		F32 range_min = mAutoScaleMin ? llmin(mMinBar, min) : mMinBar;
+		F32 range_max = mAutoScaleMax ? llmax(mMaxBar, max) : mMaxBar;
+		F32 tick_value = 0.f;
+		calc_auto_scale_range(range_min, range_max, tick_value);
+		if (mAutoScaleMin) { mMinBar = range_min; }
+		if (mAutoScaleMax) { mMaxBar = range_max; }
+		if (mAutoScaleMin && mAutoScaleMax)
+		{
+			mTickValue = tick_value;
+		}
+		else
+		{
+			mTickValue = calc_tick_value(mMinBar, mMaxBar);
+		}
+	}
+
+	// start counting from actual min, not current, animating min, so that ticks don't float between numbers
+	// ensure ticks always hit 0
+	S32 last_tick = 0;
+	S32 last_label = 0;
+	if (mTickValue > 0.f && value_scale > 0.f)
+	{
+		const S32 MIN_TICK_SPACING  = mOrientation == HORIZONTAL ? 20 : 30;
+		const S32 MIN_LABEL_SPACING = mOrientation == HORIZONTAL ? 30 : 60;
+		const S32 TICK_LENGTH = 4;
+		const S32 TICK_WIDTH = 1;
+
+		F32 start = mCurMinBar < 0.f
+			? llceil(-mCurMinBar / mTickValue) * -mTickValue
+			: 0.f;
+		for (F32 tick_value = start; ;tick_value += mTickValue)
+		{
+			const S32 begin = llfloor((tick_value - mCurMinBar)*value_scale);
+			const S32 end = begin + TICK_WIDTH;
+			if (begin - last_tick < MIN_TICK_SPACING)
+			{
+				continue;
+			}
+			last_tick = begin;
+
+			S32 decimal_digits = mDecimalDigits;
+			if (is_approx_equal((F32)(S32)tick_value, tick_value))
+			{
+				decimal_digits = 0;
+			}
+			std::string tick_string = llformat("%10.*f", decimal_digits, tick_value);
+
+			if (mOrientation == HORIZONTAL)
+			{
+				if (begin - last_label > MIN_LABEL_SPACING)
+				{
+					gl_rect_2d(bar_rect.mLeft, end, bar_rect.mRight - TICK_LENGTH, begin, LLColor4(1.f, 1.f, 1.f, 0.25f));
+					LLFontGL::getFontMonospace()->renderUTF8(tick_string, 0, bar_rect.mRight, begin,
+						LLColor4(1.f, 1.f, 1.f, 0.5f),
+						LLFontGL::LEFT, LLFontGL::VCENTER);
+					last_label = begin;
+				}
+				else
+				{
+					gl_rect_2d(bar_rect.mLeft, end, bar_rect.mRight - TICK_LENGTH/2, begin, LLColor4(1.f, 1.f, 1.f, 0.1f));
+				}
+			}
+			else
+			{
+				if (begin - last_label > MIN_LABEL_SPACING)
+				{
+					gl_rect_2d(begin, bar_rect.mTop, end, bar_rect.mBottom - TICK_LENGTH, LLColor4(1.f, 1.f, 1.f, 0.25f));
+					LLFontGL::getFontMonospace()->renderUTF8(tick_string, 0, begin - 1, bar_rect.mBottom - TICK_LENGTH,
+						LLColor4(1.f, 1.f, 1.f, 0.5f),
+						LLFontGL::RIGHT, LLFontGL::TOP);
+					last_label = begin;
+				}
+				else
+				{
+					gl_rect_2d(begin, bar_rect.mTop, end, bar_rect.mBottom - TICK_LENGTH/2, LLColor4(1.f, 1.f, 1.f, 0.1f));
+				}
+			}
+			// always draw one tick value past end, so we can see part of the text, if possible
+			if (tick_value > mCurMaxBar)
+			{
+				break;
+			}
+		}
+	}
+}
+
+
+
diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h
index 5aed98fecf0..dd4d9400a5d 100755
--- a/indra/llui/llstatbar.h
+++ b/indra/llui/llstatbar.h
@@ -89,6 +89,9 @@ class LLStatBar : public LLView
 	/*virtual*/ LLRect getRequiredRect();	// Return the height of this object, given the set options.
 
 private:
+	void drawLabelAndValue( F32 mean, std::string &unit_label, LLRect &bar_rect );
+	void drawTicks( F32 min, F32 max, F32 value_scale, LLRect &bar_rect );
+
 	F32          mMinBar,
 				 mMaxBar,
 				 mCurMaxBar,
@@ -104,10 +107,12 @@ class LLStatBar : public LLView
 				 mAutoScaleMax,
 				 mAutoScaleMin;
 	EOrientation mOrientation;
+	F32			 mLastDisplayValue;
+	LLFrameTimer mLastDisplayValueTimer;
 
-	LLTrace::TraceType<LLTrace::CountAccumulator>*		mCountFloatp;
-	LLTrace::TraceType<LLTrace::EventAccumulator>*		mEventFloatp;
-	LLTrace::TraceType<LLTrace::SampleAccumulator>*		mSampleFloatp;
+	const LLTrace::TraceType<LLTrace::CountAccumulator>*		mCountFloatp;
+	const LLTrace::TraceType<LLTrace::EventAccumulator>*		mEventFloatp;
+	const LLTrace::TraceType<LLTrace::SampleAccumulator>*		mSampleFloatp;
 
 	LLUIString   mLabel;
 	std::string  mUnitLabel;
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
index 4cbf84be73e..6a1f937340f 100755
--- a/indra/llui/llxuiparser.cpp
+++ b/indra/llui/llxuiparser.cpp
@@ -1313,7 +1313,7 @@ void LLXUIParser::parserWarning(const std::string& message)
 {
 #ifdef LL_WINDOWS
 	// use Visual Studio friendly formatting of output message for easy access to originating xml
-	LL_WINDOWS_OUTPUT_DEBUG(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()));
+	LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()) << LL_ENDL;
 #else
 	Parser::parserWarning(message);
 #endif
@@ -1322,8 +1322,8 @@ void LLXUIParser::parserWarning(const std::string& message)
 void LLXUIParser::parserError(const std::string& message)
 {
 #ifdef LL_WINDOWS
-        // use Visual Studio friendly formatting of output message for easy access to originating xml
-	LL_WINDOWS_OUTPUT_DEBUG(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()));
+    // use Visual Studio friendly formatting of output message for easy access to originating xml
+	LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()) << LL_ENDL;
 #else
 	Parser::parserError(message);
 #endif
@@ -1641,7 +1641,7 @@ void LLSimpleXUIParser::parserWarning(const std::string& message)
 {
 #ifdef LL_WINDOWS
 	// use Visual Studio friendly formatting of output message for easy access to originating xml
-	LL_WINDOWS_OUTPUT_DEBUG(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()));
+	LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()) << LL_ENDL;
 #else
 	Parser::parserWarning(message);
 #endif
@@ -1651,7 +1651,7 @@ void LLSimpleXUIParser::parserError(const std::string& message)
 {
 #ifdef LL_WINDOWS
         // use Visual Studio friendly formatting of output message for easy access to originating xml
-	LL_WINDOWS_OUTPUT_DEBUG(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()));
+	LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()) << LL_ENDL;
 #else
 	Parser::parserError(message);
 #endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1b779e5c99d..b3e55ccc008 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2259,11 +2259,6 @@ if (LL_TESTS)
     "${test_libs}"
     )
 
-  LL_ADD_INTEGRATION_TEST(llsimplestat
-    ""
-    "${test_libs}"
-    )
-
   LL_ADD_INTEGRATION_TEST(llviewerassetstats
     llviewerassetstats.cpp
     "${test_libs}"
diff --git a/indra/newview/llsimplestat.h b/indra/newview/llsimplestat.h
deleted file mode 100755
index 80ce99b7740..00000000000
--- a/indra/newview/llsimplestat.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/** 
- * @file llsimplestat.h
- * @brief Runtime statistics accumulation.
- *
- * $LicenseInfo:firstyear=2010&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$
- */
-
-#ifndef LL_SIMPLESTAT_H
-#define LL_SIMPLESTAT_H
-
-// History
-//
-// The original source for this code is the server repositories'
-// llcommon/llstat.h file.  This particular code was added after the
-// viewer/server code schism but before the effort to convert common
-// code to libraries was complete.  Rather than add to merge issues,
-// the needed code was cut'n'pasted into this new header as it isn't
-// too awful a burden.  Post-modularization, we can look at removing
-// this redundancy.
-
-
-/**
- * @class LLSimpleStatCounter
- * @brief Just counts events.
- *
- * Really not needed but have a pattern in mind in the future.
- * Interface limits what can be done at that's just fine.
- *
- * *TODO:  Update/transfer unit tests
- * Unit tests:  indra/test/llcommon_llstat_tut.cpp
- */
-class LLSimpleStatCounter
-{
-public:
-	inline LLSimpleStatCounter()		{ reset(); }
-	// Default destructor and assignment operator are valid
-
-	inline void reset()					{ mCount = 0; }
-
-	inline void merge(const LLSimpleStatCounter & src)
-										{ mCount += src.mCount; }
-	
-	inline U32 operator++()				{ return ++mCount; }
-
-	inline U32 getCount() const			{ return mCount; }
-		
-protected:
-	U32			mCount;
-};
-
-
-/**
- * @class LLSimpleStatMMM
- * @brief Templated collector of min, max and mean data for stats.
- *
- * Fed a stream of data samples, keeps a running account of the
- * min, max and mean seen since construction or the last reset()
- * call.  A freshly-constructed or reset instance returns counts
- * and values of zero.
- *
- * Overflows and underflows (integer, inf or -inf) and NaN's
- * are the caller's problem.  As is loss of precision when
- * the running sum's exponent (when parameterized by a floating
- * point of some type) differs from a given data sample's.
- *
- * Unit tests:  indra/test/llcommon_llstat_tut.cpp
- */
-template <typename VALUE_T = F32>
-class LLSimpleStatMMM
-{
-public:
-	typedef VALUE_T Value;
-	
-public:
-	LLSimpleStatMMM()				{ reset(); }
-	// Default destructor and assignment operator are valid
-
-	/**
-	 * Resets the object returning all counts and derived
-	 * values back to zero.
-	 */
-	void reset()
-	{
-		mCount = 0;
-		mMin = Value(0);
-		mMax = Value(0);
-		mTotal = Value(0);
-	}
-
-	void record(Value v)
-	{
-		if (mCount)
-		{
-			mMin = llmin(mMin, v);
-			mMax = llmax(mMax, v);
-		}
-		else
-		{
-			mMin = v;
-			mMax = v;
-		}
-		mTotal += v;
-		++mCount;
-	}
-
-	void merge(const LLSimpleStatMMM<VALUE_T> & src)
-	{
-		if (! mCount)
-		{
-			*this = src;
-		}
-		else if (src.mCount)
-		{
-			mMin = llmin(mMin, src.mMin);
-			mMax = llmax(mMax, src.mMax);
-			mCount += src.mCount;
-			mTotal += src.mTotal;
-		}
-	}
-	
-	inline U32 getCount() const		{ return mCount; }
-	inline Value getMin() const		{ return mMin; }
-	inline Value getMax() const		{ return mMax; }
-	inline Value getMean() const	{ return mCount ? mTotal / mCount : mTotal; }
-		
-protected:
-	U32			mCount;
-	Value		mMin;
-	Value		mMax;
-	Value		mTotal;
-};
-
-#endif // LL_SIMPLESTAT_H
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index 2126d569f81..a42060d4d82 100755
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -34,7 +34,6 @@
 #include "llrefcount.h"
 #include "llviewerassettype.h"
 #include "llviewerassetstorage.h"
-#include "llsimplestat.h"
 #include "llsd.h"
 #include "llvoavatar.h"
 #include "lltrace.h"
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
index d4dbb487f16..2a31524e1ed 100755
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -28,7 +28,6 @@
                  label="Basic"
                  follows="left|top|right"
                  show_label="true"
-                 show_bar="true"
                  setting="OpenDebugStatBasic">
         <stat_bar name="fps"
                   label="FPS"
diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml
index 97a5ae7d4e5..807b67d1125 100755
--- a/indra/newview/skins/default/xui/en/widgets/floater.xml
+++ b/indra/newview/skins/default/xui/en/widgets/floater.xml
@@ -2,7 +2,6 @@
 <!-- See also settings.xml UIFloater* settings for configuration -->
 <floater
  name="floater"
- positioning="none"
  layout="topleft"
  bg_opaque_color="FloaterFocusBackgroundColor"
  bg_alpha_color="FloaterDefaultBackgroundColor"
diff --git a/indra/newview/tests/llsimplestat_test.cpp b/indra/newview/tests/llsimplestat_test.cpp
deleted file mode 100755
index b556941f4af..00000000000
--- a/indra/newview/tests/llsimplestat_test.cpp
+++ /dev/null
@@ -1,580 +0,0 @@
-/** 
- * @file llsimplestats_test.cpp
- * @date 2010-10-22
- * @brief Test cases for some of llsimplestat.h
- *
- * $LicenseInfo:firstyear=2010&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 <tut/tut.hpp>
-
-#include "lltut.h"
-#include "../llsimplestat.h"
-#include "llsd.h"
-#include "llmath.h"
-
-// @brief Used as a pointer cast type to get access to LLSimpleStatCounter
-class TutStatCounter: public LLSimpleStatCounter
-{
-public:
-	TutStatCounter();							// Not defined
-	~TutStatCounter();							// Not defined
-	void operator=(const TutStatCounter &);		// Not defined
-	
-	void setRawCount(U32 c)				{ mCount = c; }
-	U32 getRawCount() const				{ return mCount; }
-};
-
-
-namespace tut
-{
-	struct stat_counter_index
-	{};
-	typedef test_group<stat_counter_index> stat_counter_index_t;
-	typedef stat_counter_index_t::object stat_counter_index_object_t;
-	tut::stat_counter_index_t tut_stat_counter_index("stat_counter_test");
-
-	// Testing LLSimpleStatCounter's external interface
-	template<> template<>
-	void stat_counter_index_object_t::test<1>()
-	{
-		LLSimpleStatCounter c1;
-		ensure("Initialized counter is zero", (0 == c1.getCount()));
-
-		ensure("Counter increment return is 1", (1 == ++c1));
-		ensure("Counter increment return is 2", (2 == ++c1));
-
-		ensure("Current counter is 2", (2 == c1.getCount()));
-
-		c1.reset();
-		ensure("Counter is 0 after reset", (0 == c1.getCount()));
-		
-		ensure("Counter increment return is 1", (1 == ++c1));
-	}
-
-	// Testing LLSimpleStatCounter's internal state
-	template<> template<>
-	void stat_counter_index_object_t::test<2>()
-	{
-		LLSimpleStatCounter c1;
-		TutStatCounter * tc1 = (TutStatCounter *) &c1;
-		
-		ensure("Initialized private counter is zero", (0 == tc1->getRawCount()));
-
-		++c1;
-		++c1;
-		
-		ensure("Current private counter is 2", (2 == tc1->getRawCount()));
-
-		c1.reset();
-		ensure("Raw counter is 0 after reset", (0 == tc1->getRawCount()));
-	}
-
-	// Testing LLSimpleStatCounter's wrapping behavior
-	template<> template<>
-	void stat_counter_index_object_t::test<3>()
-	{
-		LLSimpleStatCounter c1;
-		TutStatCounter * tc1 = (TutStatCounter *) &c1;
-
-		tc1->setRawCount(U32_MAX);
-		ensure("Initialized private counter is zero", (U32_MAX == c1.getCount()));
-
-		ensure("Increment of max value wraps to 0", (0 == ++c1));
-	}
-
-	// Testing LLSimpleStatMMM's external behavior
-	template<> template<>
-	void stat_counter_index_object_t::test<4>()
-	{
-		LLSimpleStatMMM<> m1;
-		typedef LLSimpleStatMMM<>::Value lcl_float;
-		lcl_float zero(0);
-
-		// Freshly-constructed
-		ensure("Constructed MMM<> has 0 count", (0 == m1.getCount()));
-		ensure("Constructed MMM<> has 0 min", (zero == m1.getMin()));
-		ensure("Constructed MMM<> has 0 max", (zero == m1.getMax()));
-		ensure("Constructed MMM<> has 0 mean no div-by-zero", (zero == m1.getMean()));
-
-		// Single insert
-		m1.record(1.0);
-		ensure("Single insert MMM<> has 1 count", (1 == m1.getCount()));
-		ensure("Single insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("Single insert MMM<> has 1.0 max", (1.0 == m1.getMax()));
-		ensure("Single insert MMM<> has 1.0 mean", (1.0 == m1.getMean()));
-		
-		// Second insert
-		m1.record(3.0);
-		ensure("2nd insert MMM<> has 2 count", (2 == m1.getCount()));
-		ensure("2nd insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("2nd insert MMM<> has 3.0 max", (3.0 == m1.getMax()));
-		ensure_approximately_equals("2nd insert MMM<> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
-
-		// Third insert
-		m1.record(5.0);
-		ensure("3rd insert MMM<> has 3 count", (3 == m1.getCount()));
-		ensure("3rd insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("3rd insert MMM<> has 5.0 max", (5.0 == m1.getMax()));
-		ensure_approximately_equals("3rd insert MMM<> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
-
-		// Fourth insert
-		m1.record(1000000.0);
-		ensure("4th insert MMM<> has 4 count", (4 == m1.getCount()));
-		ensure("4th insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("4th insert MMM<> has 100000.0 max", (1000000.0 == m1.getMax()));
-		ensure_approximately_equals("4th insert MMM<> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
-
-		// Reset
-		m1.reset();
-		ensure("Reset MMM<> has 0 count", (0 == m1.getCount()));
-		ensure("Reset MMM<> has 0 min", (zero == m1.getMin()));
-		ensure("Reset MMM<> has 0 max", (zero == m1.getMax()));
-		ensure("Reset MMM<> has 0 mean no div-by-zero", (zero == m1.getMean()));
-	}
-
-	// Testing LLSimpleStatMMM's response to large values
-	template<> template<>
-	void stat_counter_index_object_t::test<5>()
-	{
-		LLSimpleStatMMM<> m1;
-		typedef LLSimpleStatMMM<>::Value lcl_float;
-		lcl_float zero(0);
-
-		// Insert overflowing values
-		const lcl_float bignum(F32_MAX / 2);
-
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(zero);
-
-		ensure("Overflowed MMM<> has 8 count", (8 == m1.getCount()));
-		ensure("Overflowed MMM<> has 0 min", (zero == m1.getMin()));
-		ensure("Overflowed MMM<> has huge max", (bignum == m1.getMax()));
-		ensure("Overflowed MMM<> has fetchable mean", (1.0 == m1.getMean() || true));
-		// We should be infinte but not interested in proving the IEEE standard here.
-		LLSD sd1(m1.getMean());
-		// std::cout << "Thingy:  " << m1.getMean() << " and as LLSD:  " << sd1 << std::endl;
-		ensure("Overflowed MMM<> produces LLSDable Real", (sd1.isReal()));
-	}
-
-	// Testing LLSimpleStatMMM<F32>'s external behavior
-	template<> template<>
-	void stat_counter_index_object_t::test<6>()
-	{
-		LLSimpleStatMMM<F32> m1;
-		typedef LLSimpleStatMMM<F32>::Value lcl_float;
-		lcl_float zero(0);
-
-		// Freshly-constructed
-		ensure("Constructed MMM<F32> has 0 count", (0 == m1.getCount()));
-		ensure("Constructed MMM<F32> has 0 min", (zero == m1.getMin()));
-		ensure("Constructed MMM<F32> has 0 max", (zero == m1.getMax()));
-		ensure("Constructed MMM<F32> has 0 mean no div-by-zero", (zero == m1.getMean()));
-
-		// Single insert
-		m1.record(1.0);
-		ensure("Single insert MMM<F32> has 1 count", (1 == m1.getCount()));
-		ensure("Single insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("Single insert MMM<F32> has 1.0 max", (1.0 == m1.getMax()));
-		ensure("Single insert MMM<F32> has 1.0 mean", (1.0 == m1.getMean()));
-		
-		// Second insert
-		m1.record(3.0);
-		ensure("2nd insert MMM<F32> has 2 count", (2 == m1.getCount()));
-		ensure("2nd insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("2nd insert MMM<F32> has 3.0 max", (3.0 == m1.getMax()));
-		ensure_approximately_equals("2nd insert MMM<F32> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
-
-		// Third insert
-		m1.record(5.0);
-		ensure("3rd insert MMM<F32> has 3 count", (3 == m1.getCount()));
-		ensure("3rd insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("3rd insert MMM<F32> has 5.0 max", (5.0 == m1.getMax()));
-		ensure_approximately_equals("3rd insert MMM<F32> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
-
-		// Fourth insert
-		m1.record(1000000.0);
-		ensure("4th insert MMM<F32> has 4 count", (4 == m1.getCount()));
-		ensure("4th insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("4th insert MMM<F32> has 1000000.0 max", (1000000.0 == m1.getMax()));
-		ensure_approximately_equals("4th insert MMM<F32> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
-
-		// Reset
-		m1.reset();
-		ensure("Reset MMM<F32> has 0 count", (0 == m1.getCount()));
-		ensure("Reset MMM<F32> has 0 min", (zero == m1.getMin()));
-		ensure("Reset MMM<F32> has 0 max", (zero == m1.getMax()));
-		ensure("Reset MMM<F32> has 0 mean no div-by-zero", (zero == m1.getMean()));
-	}
-
-	// Testing LLSimpleStatMMM's response to large values
-	template<> template<>
-	void stat_counter_index_object_t::test<7>()
-	{
-		LLSimpleStatMMM<F32> m1;
-		typedef LLSimpleStatMMM<F32>::Value lcl_float;
-		lcl_float zero(0);
-
-		// Insert overflowing values
-		const lcl_float bignum(F32_MAX / 2);
-
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(zero);
-
-		ensure("Overflowed MMM<F32> has 8 count", (8 == m1.getCount()));
-		ensure("Overflowed MMM<F32> has 0 min", (zero == m1.getMin()));
-		ensure("Overflowed MMM<F32> has huge max", (bignum == m1.getMax()));
-		ensure("Overflowed MMM<F32> has fetchable mean", (1.0 == m1.getMean() || true));
-		// We should be infinte but not interested in proving the IEEE standard here.
-		LLSD sd1(m1.getMean());
-		// std::cout << "Thingy:  " << m1.getMean() << " and as LLSD:  " << sd1 << std::endl;
-		ensure("Overflowed MMM<F32> produces LLSDable Real", (sd1.isReal()));
-	}
-
-	// Testing LLSimpleStatMMM<F64>'s external behavior
-	template<> template<>
-	void stat_counter_index_object_t::test<8>()
-	{
-		LLSimpleStatMMM<F64> m1;
-		typedef LLSimpleStatMMM<F64>::Value lcl_float;
-		lcl_float zero(0);
-
-		// Freshly-constructed
-		ensure("Constructed MMM<F64> has 0 count", (0 == m1.getCount()));
-		ensure("Constructed MMM<F64> has 0 min", (zero == m1.getMin()));
-		ensure("Constructed MMM<F64> has 0 max", (zero == m1.getMax()));
-		ensure("Constructed MMM<F64> has 0 mean no div-by-zero", (zero == m1.getMean()));
-
-		// Single insert
-		m1.record(1.0);
-		ensure("Single insert MMM<F64> has 1 count", (1 == m1.getCount()));
-		ensure("Single insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("Single insert MMM<F64> has 1.0 max", (1.0 == m1.getMax()));
-		ensure("Single insert MMM<F64> has 1.0 mean", (1.0 == m1.getMean()));
-		
-		// Second insert
-		m1.record(3.0);
-		ensure("2nd insert MMM<F64> has 2 count", (2 == m1.getCount()));
-		ensure("2nd insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("2nd insert MMM<F64> has 3.0 max", (3.0 == m1.getMax()));
-		ensure_approximately_equals("2nd insert MMM<F64> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
-
-		// Third insert
-		m1.record(5.0);
-		ensure("3rd insert MMM<F64> has 3 count", (3 == m1.getCount()));
-		ensure("3rd insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("3rd insert MMM<F64> has 5.0 max", (5.0 == m1.getMax()));
-		ensure_approximately_equals("3rd insert MMM<F64> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
-
-		// Fourth insert
-		m1.record(1000000.0);
-		ensure("4th insert MMM<F64> has 4 count", (4 == m1.getCount()));
-		ensure("4th insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
-		ensure("4th insert MMM<F64> has 1000000.0 max", (1000000.0 == m1.getMax()));
-		ensure_approximately_equals("4th insert MMM<F64> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
-
-		// Reset
-		m1.reset();
-		ensure("Reset MMM<F64> has 0 count", (0 == m1.getCount()));
-		ensure("Reset MMM<F64> has 0 min", (zero == m1.getMin()));
-		ensure("Reset MMM<F64> has 0 max", (zero == m1.getMax()));
-		ensure("Reset MMM<F64> has 0 mean no div-by-zero", (zero == m1.getMean()));
-	}
-
-	// Testing LLSimpleStatMMM's response to large values
-	template<> template<>
-	void stat_counter_index_object_t::test<9>()
-	{
-		LLSimpleStatMMM<F64> m1;
-		typedef LLSimpleStatMMM<F64>::Value lcl_float;
-		lcl_float zero(0);
-
-		// Insert overflowing values
-		const lcl_float bignum(F64_MAX / 2);
-
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(zero);
-
-		ensure("Overflowed MMM<F64> has 8 count", (8 == m1.getCount()));
-		ensure("Overflowed MMM<F64> has 0 min", (zero == m1.getMin()));
-		ensure("Overflowed MMM<F64> has huge max", (bignum == m1.getMax()));
-		ensure("Overflowed MMM<F64> has fetchable mean", (1.0 == m1.getMean() || true));
-		// We should be infinte but not interested in proving the IEEE standard here.
-		LLSD sd1(m1.getMean());
-		// std::cout << "Thingy:  " << m1.getMean() << " and as LLSD:  " << sd1 << std::endl;
-		ensure("Overflowed MMM<F64> produces LLSDable Real", (sd1.isReal()));
-	}
-
-	// Testing LLSimpleStatMMM<U64>'s external behavior
-	template<> template<>
-	void stat_counter_index_object_t::test<10>()
-	{
-		LLSimpleStatMMM<U64> m1;
-		typedef LLSimpleStatMMM<U64>::Value lcl_int;
-		lcl_int zero(0);
-
-		// Freshly-constructed
-		ensure("Constructed MMM<U64> has 0 count", (0 == m1.getCount()));
-		ensure("Constructed MMM<U64> has 0 min", (zero == m1.getMin()));
-		ensure("Constructed MMM<U64> has 0 max", (zero == m1.getMax()));
-		ensure("Constructed MMM<U64> has 0 mean no div-by-zero", (zero == m1.getMean()));
-
-		// Single insert
-		m1.record(1);
-		ensure("Single insert MMM<U64> has 1 count", (1 == m1.getCount()));
-		ensure("Single insert MMM<U64> has 1 min", (1 == m1.getMin()));
-		ensure("Single insert MMM<U64> has 1 max", (1 == m1.getMax()));
-		ensure("Single insert MMM<U64> has 1 mean", (1 == m1.getMean()));
-		
-		// Second insert
-		m1.record(3);
-		ensure("2nd insert MMM<U64> has 2 count", (2 == m1.getCount()));
-		ensure("2nd insert MMM<U64> has 1 min", (1 == m1.getMin()));
-		ensure("2nd insert MMM<U64> has 3 max", (3 == m1.getMax()));
-		ensure("2nd insert MMM<U64> has 2 mean", (2 == m1.getMean()));
-
-		// Third insert
-		m1.record(5);
-		ensure("3rd insert MMM<U64> has 3 count", (3 == m1.getCount()));
-		ensure("3rd insert MMM<U64> has 1 min", (1 == m1.getMin()));
-		ensure("3rd insert MMM<U64> has 5 max", (5 == m1.getMax()));
-		ensure("3rd insert MMM<U64> has 3 mean", (3 == m1.getMean()));
-
-		// Fourth insert
-		m1.record(U64L(1000000000000));
-		ensure("4th insert MMM<U64> has 4 count", (4 == m1.getCount()));
-		ensure("4th insert MMM<U64> has 1 min", (1 == m1.getMin()));
-		ensure("4th insert MMM<U64> has 1000000000000ULL max", (U64L(1000000000000) == m1.getMax()));
-		ensure("4th insert MMM<U64> has 250000000002ULL mean", (U64L( 250000000002) == m1.getMean()));
-
-		// Reset
-		m1.reset();
-		ensure("Reset MMM<U64> has 0 count", (0 == m1.getCount()));
-		ensure("Reset MMM<U64> has 0 min", (zero == m1.getMin()));
-		ensure("Reset MMM<U64> has 0 max", (zero == m1.getMax()));
-		ensure("Reset MMM<U64> has 0 mean no div-by-zero", (zero == m1.getMean()));
-	}
-
-	// Testing LLSimpleStatMMM's response to large values
-	template<> template<>
-	void stat_counter_index_object_t::test<11>()
-	{
-		LLSimpleStatMMM<U64> m1;
-		typedef LLSimpleStatMMM<U64>::Value lcl_int;
-		lcl_int zero(0);
-
-		// Insert overflowing values
-		const lcl_int bignum(U64L(0xffffffffffffffff) / 2);
-
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(bignum);
-		m1.record(zero);
-
-		ensure("Overflowed MMM<U64> has 8 count", (8 == m1.getCount()));
-		ensure("Overflowed MMM<U64> has 0 min", (zero == m1.getMin()));
-		ensure("Overflowed MMM<U64> has huge max", (bignum == m1.getMax()));
-		ensure("Overflowed MMM<U64> has fetchable mean", (zero == m1.getMean() || true));
-	}
-
-    // Testing LLSimpleStatCounter's merge() method
-	template<> template<>
-	void stat_counter_index_object_t::test<12>()
-	{
-		LLSimpleStatCounter c1;
-		LLSimpleStatCounter c2;
-
-		++c1;
-		++c1;
-		++c1;
-		++c1;
-
-		++c2;
-		++c2;
-		c2.merge(c1);
-		
-		ensure_equals("4 merged into 2 results in 6", 6, c2.getCount());
-
-		ensure_equals("Source of merge is undamaged", 4, c1.getCount());
-	}
-
-    // Testing LLSimpleStatMMM's merge() method
-	template<> template<>
-	void stat_counter_index_object_t::test<13>()
-	{
-		LLSimpleStatMMM<> m1;
-		LLSimpleStatMMM<> m2;
-
-		m1.record(3.5);
-		m1.record(4.5);
-		m1.record(5.5);
-		m1.record(6.5);
-
-		m2.record(5.0);
-		m2.record(7.0);
-		m2.record(9.0);
-		
-		m2.merge(m1);
-
-		ensure_equals("Count after merge (p1)", 7, m2.getCount());
-		ensure_approximately_equals("Min after merge (p1)", F32(3.5), m2.getMin(), 22);
-		ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22);
-		ensure_approximately_equals("Mean after merge (p1)", F32(41.000/7.000), m2.getMean(), 22);
-		
-
-		ensure_equals("Source count of merge is undamaged (p1)", 4, m1.getCount());
-		ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(3.5), m1.getMin(), 22);
-		ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(6.5), m1.getMax(), 22);
-		ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(5.0), m1.getMean(), 22);
-
-		m2.reset();
-
-		m2.record(-22.0);
-		m2.record(-1.0);
-		m2.record(30.0);
-		
-		m2.merge(m1);
-
-		ensure_equals("Count after merge (p2)", 7, m2.getCount());
-		ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22);
-		ensure_approximately_equals("Max after merge (p2)", F32(30.0), m2.getMax(), 22);
-		ensure_approximately_equals("Mean after merge (p2)", F32(27.000/7.000), m2.getMean(), 22);
-
-	}
-
-    // Testing LLSimpleStatMMM's merge() method when src contributes nothing
-	template<> template<>
-	void stat_counter_index_object_t::test<14>()
-	{
-		LLSimpleStatMMM<> m1;
-		LLSimpleStatMMM<> m2;
-
-		m2.record(5.0);
-		m2.record(7.0);
-		m2.record(9.0);
-		
-		m2.merge(m1);
-
-		ensure_equals("Count after merge (p1)", 3, m2.getCount());
-		ensure_approximately_equals("Min after merge (p1)", F32(5.0), m2.getMin(), 22);
-		ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22);
-		ensure_approximately_equals("Mean after merge (p1)", F32(7.000), m2.getMean(), 22);
-
-		ensure_equals("Source count of merge is undamaged (p1)", 0, m1.getCount());
-		ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(0), m1.getMin(), 22);
-		ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(0), m1.getMax(), 22);
-		ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(0), m1.getMean(), 22);
-
-		m2.reset();
-
-		m2.record(-22.0);
-		m2.record(-1.0);
-		
-		m2.merge(m1);
-
-		ensure_equals("Count after merge (p2)", 2, m2.getCount());
-		ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22);
-		ensure_approximately_equals("Max after merge (p2)", F32(-1.0), m2.getMax(), 22);
-		ensure_approximately_equals("Mean after merge (p2)", F32(-11.5), m2.getMean(), 22);
-	}
-
-    // Testing LLSimpleStatMMM's merge() method when dst contributes nothing
-	template<> template<>
-	void stat_counter_index_object_t::test<15>()
-	{
-		LLSimpleStatMMM<> m1;
-		LLSimpleStatMMM<> m2;
-
-		m1.record(5.0);
-		m1.record(7.0);
-		m1.record(9.0);
-		
-		m2.merge(m1);
-
-		ensure_equals("Count after merge (p1)", 3, m2.getCount());
-		ensure_approximately_equals("Min after merge (p1)", F32(5.0), m2.getMin(), 22);
-		ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22);
-		ensure_approximately_equals("Mean after merge (p1)", F32(7.000), m2.getMean(), 22);
-
-		ensure_equals("Source count of merge is undamaged (p1)", 3, m1.getCount());
-		ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(5.0), m1.getMin(), 22);
-		ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(9.0), m1.getMax(), 22);
-		ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(7.0), m1.getMean(), 22);
-
-		m1.reset();
-		m2.reset();
-		
-		m1.record(-22.0);
-		m1.record(-1.0);
-		
-		m2.merge(m1);
-
-		ensure_equals("Count after merge (p2)", 2, m2.getCount());
-		ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22);
-		ensure_approximately_equals("Max after merge (p2)", F32(-1.0), m2.getMax(), 22);
-		ensure_approximately_equals("Mean after merge (p2)", F32(-11.5), m2.getMean(), 22);
-	}
-
-    // Testing LLSimpleStatMMM's merge() method when neither dst nor src contributes
-	template<> template<>
-	void stat_counter_index_object_t::test<16>()
-	{
-		LLSimpleStatMMM<> m1;
-		LLSimpleStatMMM<> m2;
-
-		m2.merge(m1);
-
-		ensure_equals("Count after merge (p1)", 0, m2.getCount());
-		ensure_approximately_equals("Min after merge (p1)", F32(0), m2.getMin(), 22);
-		ensure_approximately_equals("Max after merge (p1)", F32(0), m2.getMax(), 22);
-		ensure_approximately_equals("Mean after merge (p1)", F32(0), m2.getMean(), 22);
-
-		ensure_equals("Source count of merge is undamaged (p1)", 0, m1.getCount());
-		ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(0), m1.getMin(), 22);
-		ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(0), m1.getMax(), 22);
-		ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(0), m1.getMean(), 22);
-	}
-}
diff --git a/indra/test/io.cpp b/indra/test/io.cpp
index 261422e9fc6..97726c2b929 100755
--- a/indra/test/io.cpp
+++ b/indra/test/io.cpp
@@ -877,11 +877,11 @@ namespace tut
 	public:
 		double_construct()
 		{
-			llinfos << "constructed" << llendl;
+			LL_INFOS() << "constructed" << LL_ENDL;
 		}
 		~double_construct()
 		{
-			llinfos << "destroyed" << llendl;
+			LL_INFOS() << "destroyed" << LL_ENDL;
 		}
 	};
 	typedef test_group<double_construct> double_construct_test_group;
@@ -938,11 +938,11 @@ namespace tut
 	template<> template<>
 	void fitness_test_object::test<1>()
 	{
-		lldebugs << "fitness_test_object::test<1>()" << llendl;
+		LL_DEBUGS() << "fitness_test_object::test<1>()" << LL_ENDL;
 
 		// Set up the server
-		//lldebugs << "fitness_test_object::test<1> - setting up server."
-		//	 << llendl;
+		//LL_DEBUGS() << "fitness_test_object::test<1> - setting up server."
+		//	 << LL_ENDL;
 		LLPumpIO::chain_t chain;
 		typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
 		emitter_t* emitter = new emitter_t(
@@ -957,18 +957,18 @@ namespace tut
 		mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
 
 		// We need to tickle the pump a little to set up the listen()
-		//lldebugs << "fitness_test_object::test<1> - initializing server."
-		//	 << llendl;
+		//LL_DEBUGS() << "fitness_test_object::test<1> - initializing server."
+		//	 << LL_ENDL;
 		pump_loop(mPump, 0.1f);
 
 		// Set up the client
-		//lldebugs << "fitness_test_object::test<1> - connecting client."
-		//	 << llendl;
+		//LL_DEBUGS() << "fitness_test_object::test<1> - connecting client."
+		//	 << LL_ENDL;
 		LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
 		LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
 		bool connected = client->blockingConnect(server_host);
 		ensure("Connected to server", connected);
-		lldebugs << "connected" << llendl;
+		LL_DEBUGS() << "connected" << LL_ENDL;
 
 		// We have connected, since the socket reader does not block,
 		// the first call to read data will return EAGAIN, so we need
@@ -988,7 +988,7 @@ namespace tut
 	template<> template<>
 	void fitness_test_object::test<2>()
 	{
-		lldebugs << "fitness_test_object::test<2>()" << llendl;
+		LL_DEBUGS() << "fitness_test_object::test<2>()" << LL_ENDL;
 
 		// Set up the server
 		LLPumpIO::chain_t chain;
@@ -1011,7 +1011,7 @@ namespace tut
 		LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
 		bool connected = client->blockingConnect(server_host);
 		ensure("Connected to server", connected);
-		lldebugs << "connected" << llendl;
+		LL_DEBUGS() << "connected" << LL_ENDL;
 
 		// We have connected, since the socket reader does not block,
 		// the first call to read data will return EAGAIN, so we need
@@ -1031,7 +1031,7 @@ namespace tut
 	template<> template<>
 	void fitness_test_object::test<3>()
 	{
-		lldebugs << "fitness_test_object::test<3>()" << llendl;
+		LL_DEBUGS() << "fitness_test_object::test<3>()" << LL_ENDL;
 
 		// Set up the server
 		LLPumpIO::chain_t chain;
@@ -1054,7 +1054,7 @@ namespace tut
 		LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
 		bool connected = client->blockingConnect(server_host);
 		ensure("Connected to server", connected);
-		lldebugs << "connected" << llendl;
+		LL_DEBUGS() << "connected" << LL_ENDL;
 
 		// We have connected, since the socket reader does not block,
 		// the first call to read data will return EAGAIN, so we need
@@ -1074,7 +1074,7 @@ namespace tut
 	template<> template<>
 	void fitness_test_object::test<4>()
 	{
-		lldebugs << "fitness_test_object::test<4>()" << llendl;
+		LL_DEBUGS() << "fitness_test_object::test<4>()" << LL_ENDL;
 
 		// Set up the server
 		LLPumpIO::chain_t chain;
@@ -1097,7 +1097,7 @@ namespace tut
 		LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
 		bool connected = client->blockingConnect(server_host);
 		ensure("Connected to server", connected);
-		lldebugs << "connected" << llendl;
+		LL_DEBUGS() << "connected" << LL_ENDL;
 
 		// We have connected, since the socket reader does not block,
 		// the first call to read data will return EAGAIN, so we need
@@ -1133,18 +1133,18 @@ namespace tut
 		pump_loop(mPump, 0.1f);
 		U32 count = mPump->runningChains();
 		ensure_equals("server chain onboard", count, 1);
-		lldebugs << "** Server is up." << llendl;
+		LL_DEBUGS() << "** Server is up." << LL_ENDL;
 
 		// Set up the client
 		LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
 		LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
 		bool connected = client->blockingConnect(server_host);
 		ensure("Connected to server", connected);
-		lldebugs << "connected" << llendl;
+		LL_DEBUGS() << "connected" << LL_ENDL;
 		pump_loop(mPump,0.1f);
 		count = mPump->runningChains();
 		ensure_equals("server chain onboard", count, 2);
-		lldebugs << "** Client is connected." << llendl;
+		LL_DEBUGS() << "** Client is connected." << LL_ENDL;
 
 		// We have connected, since the socket reader does not block,
 		// the first call to read data will return EAGAIN, so we need
@@ -1160,20 +1160,20 @@ namespace tut
 		pump_loop(mPump,0.1f);
 		count = mPump->runningChains();
 		// ensure_equals("client chain onboard", count, 3); commented out because it fails frequently - appears to be timing sensitive
-		lldebugs << "** request should have been sent." << llendl;
+		LL_DEBUGS() << "** request should have been sent." << LL_ENDL;
 
 		// pump for long enough the the client socket closes, and the
 		// server socket should not be closed yet.
 		pump_loop(mPump,0.2f);
 		count = mPump->runningChains();
 		ensure_equals("client chain timed out ", count, 2);
-		lldebugs << "** client chain should be closed." << llendl;
+		LL_DEBUGS() << "** client chain should be closed." << LL_ENDL;
 
 		// At this point, the socket should be closed by the timeout
 		pump_loop(mPump,1.0f);
 		count = mPump->runningChains();
 		ensure_equals("accepted socked close", count, 1);
-		lldebugs << "** Sleeper should have timed out.." << llendl;
+		LL_DEBUGS() << "** Sleeper should have timed out.." << LL_ENDL;
 	}
 }
 
@@ -1305,8 +1305,8 @@ namespace tut
 		LLSD request;
 		request = 1;
 		pump_loop(request);
-		//llinfos << "request: " << *request << llendl;
-		//llinfos << "response: " << *mResponse << llendl;
+		//LL_INFOS() << "request: " << *request << LL_ENDL;
+		//LL_INFOS() << "response: " << *mResponse << LL_ENDL;
 		ensure_equals("integer request response", mResponse.asInteger(), 1);
 	}
 
@@ -1559,7 +1559,7 @@ namespace tut
 		mResponse->getString(actual);
 		if(actual != expected)
 		{
-			//llwarns << "iteration " << i << llendl;
+			//LL_WARNS() << "iteration " << i << LL_ENDL;
 			std::ostringstream e_str;
 			std::string::iterator iter = expected.begin();
 			std::string::iterator end = expected.end();
@@ -1569,8 +1569,8 @@ namespace tut
 			}
 			e_str << std::endl;
 			llsd_serialize_string(e_str, expected);
-			llwarns << "expected size: " << expected.size() << llendl;
-			llwarns << "expected:	  " << e_str.str() << llendl;
+			LL_WARNS() << "expected size: " << expected.size() << LL_ENDL;
+			LL_WARNS() << "expected:	  " << e_str.str() << LL_ENDL;
 
 			std::ostringstream a_str;
 			iter = actual.begin();
@@ -1581,8 +1581,8 @@ namespace tut
 			}
 			a_str << std::endl;
 			llsd_serialize_string(a_str, actual);
-			llwarns << "actual size:	  " << actual.size() << llendl;
-			llwarns << "actual:		" << a_str.str() << llendl;
+			LL_WARNS() << "actual size:	  " << actual.size() << LL_ENDL;
+			LL_WARNS() << "actual:		" << a_str.str() << LL_ENDL;
 		}
 		ensure_equals("binary string request response", actual, expected);
 		delete request;
diff --git a/indra/test/llblowfish_tut.cpp b/indra/test/llblowfish_tut.cpp
index 2573cab81fa..96e30f4e1e8 100755
--- a/indra/test/llblowfish_tut.cpp
+++ b/indra/test/llblowfish_tut.cpp
@@ -65,14 +65,14 @@ namespace tut
 			}
 			if (!fp)
 			{
-				llwarns << "unabled to open " << filename << llendl;
+				LL_WARNS() << "unabled to open " << filename << LL_ENDL;
 				return false;
 			}
 
 			std::string good;
 			good.resize(256);
 			size_t got = fread(&good[0], 1, 256, fp);
-			lldebugs << "matchFile read " << got << llendl;
+			LL_DEBUGS() << "matchFile read " << got << LL_ENDL;
 			fclose(fp);
 			good.resize(got);
 		
diff --git a/indra/test/lliohttpserver_tut.cpp b/indra/test/lliohttpserver_tut.cpp
index 3fa5c8dd423..1513446788d 100755
--- a/indra/test/lliohttpserver_tut.cpp
+++ b/indra/test/lliohttpserver_tut.cpp
@@ -321,8 +321,8 @@ namespace tut
 			stream << "<integer>42</integer>";
 		}
 		stream << "</array></llsd>";
-		llinfos << "HTTPServiceTestObject::test<7>"
-				<< stream.str().length() << llendl;
+		LL_INFOS() << "HTTPServiceTestObject::test<7>"
+				<< stream.str().length() << LL_ENDL;
 		std::string result = httpPOST("web/echo", stream.str());
 		ensure_starts_with("large echo status", result, "HTTP/1.0 200 OK\r\n");
 	}
diff --git a/indra/test/llpermissions_tut.cpp b/indra/test/llpermissions_tut.cpp
index bc2c87ba46d..8d8d47a667d 100755
--- a/indra/test/llpermissions_tut.cpp
+++ b/indra/test/llpermissions_tut.cpp
@@ -407,7 +407,7 @@ namespace tut
 		LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
 		if(!fp)
 		{
-			llerrs << "file couldn't be opened\n" << llendl;
+			LL_ERRS() << "file couldn't be opened\n" << LL_ENDL;
 			return;
 		}
 		LLPermissions perm,perm1;
@@ -430,7 +430,7 @@ namespace tut
 		fp = LLFile::fopen("linden_file.dat","r+");
 		if(!fp)
 		{
-			llerrs << "file couldn't be opened\n" << llendl;
+			LL_ERRS() << "file couldn't be opened\n" << LL_ENDL;
 			return;
 		}
 		ensure("Permissions import failed", perm1.importFile(fp));
diff --git a/indra/test/llpipeutil.cpp b/indra/test/llpipeutil.cpp
index db76a370e01..bb706b58d5f 100755
--- a/indra/test/llpipeutil.cpp
+++ b/indra/test/llpipeutil.cpp
@@ -170,13 +170,13 @@ LLIOPipe::EStatus LLIOSleeper::process_impl(
 {
 	if(!mRespond)
 	{
-		lldebugs << "LLIOSleeper::process_impl() sleeping." << llendl;
+		LL_DEBUGS() << "LLIOSleeper::process_impl() sleeping." << LL_ENDL;
 		mRespond = true;
 		static const F64 SLEEP_TIME = 2.0;
 		pump->sleepChain(SLEEP_TIME);
 		return STATUS_BREAK;
 	}
-	lldebugs << "LLIOSleeper::process_impl() responding." << llendl;
+	LL_DEBUGS() << "LLIOSleeper::process_impl() responding." << LL_ENDL;
 	LLBufferStream ostr(channels, buffer.get());
 	ostr << "huh? sorry, I was sleeping." << std::endl;
 	return STATUS_DONE;
diff --git a/indra/test/llsaleinfo_tut.cpp b/indra/test/llsaleinfo_tut.cpp
index 2488af1d7f0..5f4d9186a80 100755
--- a/indra/test/llsaleinfo_tut.cpp
+++ b/indra/test/llsaleinfo_tut.cpp
@@ -111,7 +111,7 @@ namespace tut
 		LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
 		if(!fp)
 		{
-			llerrs << "file could not be opened\n" << llendl;
+			LL_ERRS() << "file could not be opened\n" << LL_ENDL;
 			return;
 		}
 			
@@ -128,7 +128,7 @@ namespace tut
 		
 		if(!fp)
 		{
-			llerrs << "file coudnt be opened\n" << llendl;
+			LL_ERRS() << "file coudnt be opened\n" << LL_ENDL;
 			return;
 		}
 		
-- 
GitLab