diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index ff981ca2ff7e16da9a85396745da21d415522794..b0309585aa26e71b5500f5379f336b822d18d648 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -53,30 +53,29 @@ 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);
+		ensure("default float unit is zero", float_quatloos == 0.f);
 
 		LLUnit<F32, Quatloos> float_initialize_quatloos(1);
-		ensure(float_initialize_quatloos == 1.f);
+		ensure("non-zero initialized unit", float_initialize_quatloos == 1.f);
 
 		LLUnit<S32, Quatloos> int_quatloos;
-		ensure(int_quatloos == 0);
+		ensure("default int unit is zero", int_quatloos == 0);
 
 		int_quatloos = 42;
-		ensure(int_quatloos == 42);
+		ensure("int assignment is preserved", int_quatloos == 42);
 		float_quatloos = int_quatloos;
-		ensure(float_quatloos == 42.f);
+		ensure("float assignment from int preserves value", float_quatloos == 42.f);
 
 		int_quatloos = float_quatloos;
-		ensure(int_quatloos == 42);
+		ensure("int assignment from float preserves value", int_quatloos == 42);
 
 		float_quatloos = 42.1f;
-		ensure(float_quatloos == 42.1f);
 		int_quatloos = float_quatloos;
-		ensure(int_quatloos == 42);
+		ensure("int units truncate float units on assignment", int_quatloos == 42);
+
 		LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
-		ensure(unsigned_int_quatloos == 42);
+		ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == 42);
 	}
 
 	// conversions to/from base unit
@@ -84,36 +83,35 @@ namespace tut
 	void units_object_t::test<2>()
 	{
 		LLUnit<F32, Quatloos> quatloos(1.f);
-		ensure(quatloos == 1.f);
 		LLUnit<F32, Latinum> latinum_bars(quatloos);
-		ensure(latinum_bars == 1.f / 4.f);
+		ensure("conversion between units is automatic via initialization", latinum_bars == 1.f / 4.f);
 
 		latinum_bars = 256;
 		quatloos = latinum_bars;
-		ensure(quatloos == 1024);
-
-		LLUnit<F32, Solari> solari(quatloos);
-		ensure(solari == 4096);
+		ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == 1024);
 
-		// division of integral unit
 		LLUnit<S32, Quatloos> single_quatloo(1);
 		LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
-		ensure(quarter_latinum == 0.25f);
+		ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == 0.25f);
 	}
 
 	// conversions across non-base units
 	template<> template<>
 	void units_object_t::test<3>()
 	{
-		LLUnit<F32, Solari> solari = 4.f;
+		LLUnit<F32, Quatloos> quatloos(1024);
+		LLUnit<F32, Solari> solari(quatloos);
+		ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == 4096);
+
 		LLUnit<F32, Latinum> latinum_bars = solari;
-		ensure(latinum_bars == 0.25f);
+		ensure("Non base units can be converted between each other", latinum_bars == 256);
 	}
 
 	// math operations
 	template<> template<>
 	void units_object_t::test<4>()
 	{
+		// exercise math operations
 		LLUnit<F32, Quatloos> quatloos = 1.f;
 		quatloos *= 4.f;
 		ensure(quatloos == 4);
@@ -142,44 +140,34 @@ namespace tut
 		quatloos -= 4.f;
 		ensure(quatloos == 16);
 
-		quatloos *= 2.f;
-		ensure(quatloos == 32);
-		quatloos = quatloos * 2.f;
-		ensure(quatloos == 64);
-		quatloos = 0.5f * quatloos;
-		ensure(quatloos == 32);
-
 		quatloos /= 2.f;
-		ensure(quatloos == 16);
+		ensure(quatloos == 8);
 		quatloos = quatloos / 4;
-		ensure(quatloos == 4);
+		ensure(quatloos == 2);
 
-		F32 ratio = quatloos / LLUnit<F32, Quatloos>(4.f);
+		F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f);
 		ensure(ratio == 1);
-		ratio = quatloos / LLUnit<F32, Solari>(16.f);
+		ratio = quatloos / LLUnit<F32, Solari>(8.f);
 		ensure(ratio == 1);
 
-		quatloos += LLUnit<F32, Solari>(4.f);
-		ensure(quatloos == 5);
+		quatloos += LLUnit<F32, Solari>(8.f);
+		ensure(quatloos == 4);
 		quatloos -= LLUnit<F32, Latinum>(1.f);
-		ensure(quatloos == 1);
+		ensure(quatloos == 0);
 	}
 
 	// implicit units
 	template<> template<>
 	void units_object_t::test<5>()
 	{
-		// 0-initialized
 		LLUnit<F32, Quatloos> quatloos;
-		// initialize implicit unit from explicit
 		LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + 1;
-		ensure(quatloos_implicit == 1);
+		ensure("can initialize implicit unit from explicit", quatloos_implicit == 1);
 
-		// assign implicit to explicit, or perform math operations
 		quatloos = quatloos_implicit;
-		ensure(quatloos == 1);
+		ensure("can assign implicit unit to explicit unit", quatloos == 1);
 		quatloos += quatloos_implicit;
-		ensure(quatloos == 2);
+		ensure("can perform math operation using mixture of implicit and explicit units", quatloos == 2);
 
 		// math operations on implicits
 		quatloos_implicit = 1;
@@ -211,15 +199,13 @@ namespace tut
 
 		// implicit conversion to POD
 		F32 float_val = quatloos_implicit;
-		ensure(float_val == 16);
+		ensure("implicit units convert implicitly to regular values", float_val == 16);
 
 		S32 int_val = quatloos_implicit;
-		ensure(int_val == 16);
+		ensure("implicit units convert implicitly to regular values", int_val == 16);
 
 		// conversion of implicits
 		LLUnitImplicit<F32, Latinum> latinum_implicit(2);
-		ensure(latinum_implicit == 2);
-
-		ensure(latinum_implicit * 2 == quatloos_implicit);
+		ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
 	}
 }
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
index 900f81992c1d3286cc46d9ebb8b85754b200c23f..b564ad5ceecf2cc50803de3725b94e9b67caa6e9 100755
--- a/indra/llui/llstatbar.cpp
+++ b/indra/llui/llstatbar.cpp
@@ -41,6 +41,16 @@
 #include "lllocalcliprect.h"
 #include <iostream>
 
+// rate at which to update display of value that is rapidly changing
+const F32 MEAN_VALUE_UPDATE_TIME = 1.f / 4.f; 
+// time between value changes that qualifies as a "rapid change"
+const LLUnit<F32, LLUnits::Seconds>	RAPID_CHANGE_THRESHOLD = 0.2f; 
+// maximum number of rapid changes in RAPID_CHANGE_WINDOW before switching over to displaying the mean 
+// instead of latest value
+const S32 MAX_RAPID_CHANGES_PER_SEC = 10;
+// period of time over which to measure rapid changes
+const LLUnit<F32, LLUnits::Seconds> RAPID_CHANGE_WINDOW = 1.f;
+
 F32 calc_tick_value(F32 min, F32 max)
 {
 	F32 range = max - min;
@@ -141,6 +151,25 @@ void calc_auto_scale_range(F32& min, F32& max, F32& tick)
 	max = out_max;
 }
 
+LLStatBar::Params::Params()
+:	label("label"),
+	unit_label("unit_label"),
+	bar_min("bar_min", 0.f),
+	bar_max("bar_max", 0.f),
+	tick_spacing("tick_spacing", 0.f),
+	decimal_digits("decimal_digits", 3),
+	show_bar("show_bar", false),
+	show_history("show_history", false),
+	scale_range("scale_range", true),
+	num_frames("num_frames", 200),
+	num_frames_short("num_frames_short", 20),
+	max_height("max_height", 100),
+	stat("stat"),
+	orientation("orientation", VERTICAL)
+{
+	changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT);
+}
+
 ///////////////////////////////////////////////////////////////////////////////////
 
 LLStatBar::LLStatBar(const Params& p)
@@ -253,7 +282,6 @@ S32 calc_num_rapid_changes(LLTrace::PeriodicRecording& periodic_recording, const
 	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++)
@@ -293,57 +321,50 @@ void LLStatBar::draw()
 						: 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)
 	{
 		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);
+		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);
+		display_value = mean;
 	}
 	else if (mEventFloatp)
 	{
 		const LLTrace::TraceType<LLTrace::EventAccumulator>& event_stat = *mEventFloatp;
 
-		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);
+		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, RAPID_CHANGE_WINDOW);
+		display_value     = mean;
 	}
 	else if (mSampleFloatp)
 	{
 		const LLTrace::TraceType<LLTrace::SampleAccumulator>& sample_stat = *mSampleFloatp;
 
-		unit_label = mUnitLabel.empty() ? sample_stat.getUnitLabel() : mUnitLabel;
+		unit_label        = mUnitLabel.empty() ? sample_stat.getUnitLabel() : mUnitLabel;
+		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, RAPID_CHANGE_WINDOW);
 
-		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);
-	}
-
-	if (mLastDisplayValueTimer.getElapsedTimeF32() > MIN_VALUE_UPDATE_TIME)
-	{
-		mLastDisplayValueTimer.reset();
-		display_value	= (num_rapid_changes > MAX_RAPID_CHANGES)
-			? mean
-			: current;
-		mLastDisplayValue = display_value;
-	}
-	else
-	{
-		display_value = mLastDisplayValue;
+		if (num_rapid_changes / RAPID_CHANGE_WINDOW > MAX_RAPID_CHANGES_PER_SEC)
+		{
+			display_value = mean;
+		}
+		else
+		{
+			display_value = current;
+			// always display current value, don't rate limit
+			mLastDisplayValue = current;
+		}
 	}
 
 	LLRect bar_rect;
@@ -365,7 +386,17 @@ void LLStatBar::draw()
 	mCurMaxBar = LLSmoothInterpolation::lerp(mCurMaxBar, mMaxBar, 0.05f);
 	mCurMinBar = LLSmoothInterpolation::lerp(mCurMinBar, mMinBar, 0.05f);
 
-	drawLabelAndValue(display_value, unit_label, bar_rect);
+	// rate limited updates
+	if (mLastDisplayValueTimer.getElapsedTimeF32() > MEAN_VALUE_UPDATE_TIME)
+	{
+		mLastDisplayValueTimer.reset();
+		drawLabelAndValue(display_value, unit_label, bar_rect);
+		mLastDisplayValue = display_value;
+	}
+	else
+	{
+		drawLabelAndValue(mLastDisplayValue, unit_label, bar_rect);
+	}
 
 	if (mDisplayBar
         && (mCountFloatp || mEventFloatp || mSampleFloatp))
diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h
index dd4d9400a5dfa605cda533110e057bf2c8b76cb9..bf2bd3e25929de26bea2e20d09569ddaf5a58aa2 100755
--- a/indra/llui/llstatbar.h
+++ b/indra/llui/llstatbar.h
@@ -56,24 +56,7 @@ class LLStatBar : public LLView
 		Optional<std::string>	stat;
 		Optional<EOrientation>	orientation;
 
-		Params()
-		:	label("label"),
-			unit_label("unit_label"),
-			bar_min("bar_min", 0.f),
-			bar_max("bar_max", 0.f),
-			tick_spacing("tick_spacing", 0.f),
-			decimal_digits("decimal_digits", 3),
-			show_bar("show_bar", false),
-			show_history("show_history", false),
-			scale_range("scale_range", true),
-			num_frames("num_frames", 200),
-			num_frames_short("num_frames_short", 20),
-			max_height("max_height", 100),
-			stat("stat"),
-			orientation("orientation", VERTICAL)
-		{
-			changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT);
-		}
+		Params();
 	};
 	LLStatBar(const Params&);
 
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
index 2a31524e1ed39ab0196f51bb1b972ce5de537ce4..aaf191a98a292cbf24f8af405e31b052264acefc 100755
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -31,7 +31,7 @@
                  setting="OpenDebugStatBasic">
         <stat_bar name="fps"
                   label="FPS"
-                  unit_label="frames"
+                  unit_label="fps"
                   stat="FPS"
                   decimal_digits="1"
                   show_bar="true"