diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
index ebb5961c91f266ef81ec011e7a4e53e5a48722ad..463f558c2c3c42fe025b8503ca3ae0ea07af4acd 100644
--- a/indra/llcommon/llfasttimer_class.cpp
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -303,14 +303,15 @@ LLFastTimer::NamedTimer::~NamedTimer()
 
 std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
 {
+	F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
 	if (history_idx < 0)
 	{
-		// by default, show average number of calls
-		return llformat("%s (%d calls)", getName().c_str(), (S32)getCallAverage());
+		// by default, show average number of call
+		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage());
 	}
 	else
 	{
-		return llformat("%s (%d calls)", getName().c_str(), (S32)getHistoricalCalls(history_idx));
+		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
 	}
 }
 
@@ -693,17 +694,7 @@ void LLFastTimer::nextFrame()
 		llinfos << "Slow frame, fast timers inaccurate" << llendl;
 	}
 
-	if (sPauseHistory)
-	{
-		sResetHistory = true;
-	}
-	else if (sResetHistory)
-	{
-		sLastFrameIndex = 0;
-		sCurFrameIndex = 0;
-		sResetHistory = false;
-	}
-	else // not paused
+	if (!sPauseHistory)
 	{
 		NamedTimer::processTimes();
 		sLastFrameIndex = sCurFrameIndex++;
diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h
index 827747f0c686fc87f6cc56776a7cd741f156608e..f481e968a6badaea8dba11a83eed24fc1dc6bfc1 100644
--- a/indra/llcommon/llfasttimer_class.h
+++ b/indra/llcommon/llfasttimer_class.h
@@ -66,7 +66,7 @@ class LL_COMMON_API LLFastTimer
 	public:
 		~NamedTimer();
 
-		enum { HISTORY_NUM = 60 };
+		enum { HISTORY_NUM = 300 };
 
 		const std::string& getName() const { return mName; }
 		NamedTimer* getParent() const { return mParent; }
diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index 216cc66ef8637c624294fa7b9a85960d53e367d5..cc6ba05e7e197f5e2da6e723c48d243c64cd2f7e 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -41,6 +41,7 @@
 #include "llmemoryview.h"
 #include "llsceneview.h"
 #include "llviewertexture.h"
+#include "llfloaterreg.h"
 
 //
 // Globals
@@ -79,12 +80,7 @@ void LLDebugView::init()
 	r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f), 
   									 (S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
 	
-	mFastTimerView = new LLFastTimerView(r);
-	mFastTimerView->setFollowsTop();
-	mFastTimerView->setFollowsLeft();
-	mFastTimerView->setVisible(FALSE);			// start invisible
-	addChild(mFastTimerView);
-	mFastTimerView->setRect(rect);
+	mFastTimerView = dynamic_cast<LLFastTimerView*>(LLFloaterReg::getInstance("fast_timers"));
 
 	gSceneView = new LLSceneView(r);
 	gSceneView->setFollowsTop();
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 366154302cda4270eb5cbe529da3090079fece87..a161428c2b99b2366a0775b3447ecbf08f8bb182 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -80,12 +80,10 @@ static timer_tree_iterator_t end_timer_tree()
 	return timer_tree_iterator_t(); 
 }
 
-LLFastTimerView::LLFastTimerView(const LLRect& rect)
-:	LLFloater(LLSD()),
+LLFastTimerView::LLFastTimerView(const LLSD& key)
+:	LLFloater(key),
 	mHoverTimer(NULL)
 {
-	setRect(rect);
-	setVisible(FALSE);
 	mDisplayMode = 0;
 	mAvgCountTotal = 0;
 	mMaxCountTotal = 0;
@@ -98,10 +96,30 @@ LLFastTimerView::LLFastTimerView(const LLRect& rect)
 	FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount();
 	mPrintStats = -1;	
 	mAverageCyclesPerTimer = 0;
-	setCanMinimize(false);
-	setCanClose(true);
 }
 
+void LLFastTimerView::onPause()
+{
+	LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
+	// reset scroll to bottom when unpausing
+	if (!LLFastTimer::sPauseHistory)
+	{
+		mScrollIndex = 0;
+		getChild<LLButton>("pause_btn")->setLabel(getString("pause"));
+	}
+	else
+	{
+		getChild<LLButton>("pause_btn")->setLabel(getString("run"));
+	}
+}
+
+BOOL LLFastTimerView::postBuild()
+{
+	LLButton& pause_btn = getChildRef<LLButton>("pause_btn");
+	
+	pause_btn.setCommitCallback(boost::bind(&LLFastTimerView::onPause, this));
+	return TRUE;
+}
 
 BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
@@ -116,14 +134,16 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
 		{
 			mHoverTimer->getParent()->setCollapsed(true);
 		}
+		return TRUE;
 	}
 	else if (mBarRect.pointInRect(x, y))
 	{
 		S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
 		bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY);
 		mPrintStats = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - bar_idx;
+		return TRUE;
 	}
-	return FALSE;
+	return LLFloater::handleRightMouseDown(x, y, mask);
 }
 
 LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y)
@@ -151,18 +171,6 @@ BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask)
 
 BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-
-	{
-		S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
-		S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom;
-		if(mButtons[BUTTON_CLOSE]->getVisible()
-			&&  mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y)  )
-		{
-			return LLFloater::handleMouseDown(x, y, mask);;
-		}
-	}
-	
-
 	if (x < mBarRect.mLeft) 
 	{
 		LLFastTimer::NamedTimer* idp = getLegendID(y);
@@ -196,36 +204,42 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
 	{
 		mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT);
 	}
-	else
+	else if (mGraphRect.pointInRect(x, y))
 	{
-		// pause/unpause
-		LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
-		// reset scroll to bottom when unpausing
-		if (!LLFastTimer::sPauseHistory)
-		{
-			mScrollIndex = 0;
-		}
+		gFocusMgr.setMouseCapture(this);
+		return TRUE;
 	}
-	// SJB: Don't pass mouse clicks through the display
-	return TRUE;
+	//else
+	//{
+	//	// pause/unpause
+	//	LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
+	//	// reset scroll to bottom when unpausing
+	//	if (!LLFastTimer::sPauseHistory)
+	//	{
+	//		mScrollIndex = 0;
+	//	}
+	//}
+	return LLFloater::handleMouseDown(x, y, mask);
 }
 
 BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask)
 {
+	if (hasMouseCapture())
 	{
-		S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
-		S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom;
-		if(mButtons[BUTTON_CLOSE]->getVisible()
-			&&  mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y)  )
-		{
-			return LLFloater::handleMouseUp(x, y, mask);;
-		}
+		gFocusMgr.setMouseCapture(NULL);
 	}
-	return FALSE;
+	return LLFloater::handleMouseUp(x, y, mask);;
 }
 
 BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
 {
+	if (hasMouseCapture())
+	{
+		F32 lerp = llclamp(1.f - (F32) (x - mGraphRect.mLeft) / (F32) mGraphRect.getWidth(), 0.f, 1.f);
+		mScrollIndex = llround( lerp * (F32)(LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY));
+		mScrollIndex = llclamp(	mScrollIndex, 0, LLFastTimer::getLastFrameIndex());
+		return TRUE;
+	}
 	mHoverTimer = NULL;
 	mHoverID = NULL;
 
@@ -282,7 +296,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
 		}
 	}
 	
-	return FALSE;
+	return LLFloater::handleHover(x, y, mask);
 }
 
 
@@ -318,15 +332,15 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask)
 			}
 		}
 	}
-	
-	return FALSE;
+
+	return LLFloater::handleToolTip(x, y, mask);
 }
 
 BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
 	LLFastTimer::sPauseHistory = TRUE;
-	mScrollIndex = llclamp(mScrollIndex - clicks, 
-							0, 
+	mScrollIndex = llclamp(	mScrollIndex + clicks,
+							0,
 							llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY));
 	return TRUE;
 }
@@ -345,8 +359,8 @@ void LLFastTimerView::draw()
 	F64 iclock_freq = 1000.0 / clock_freq;
 	
 	S32 margin = 10;
-	S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
-	S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f);
+	S32 height = getRect().getHeight();
+	S32 width = getRect().getWidth();
 	
 	LLRect new_rect;
 	new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
@@ -630,7 +644,6 @@ void LLFastTimerView::draw()
 										 LLFontGL::LEFT, LLFontGL::TOP);
 		}
 
-		LLRect graph_rect;
 		// Draw borders
 		{
 			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -663,9 +676,9 @@ void LLFastTimerView::draw()
 			by = LINE_GRAPH_HEIGHT-barh-dy-7;
 			
 			//line graph
-			graph_rect = LLRect(xleft-5, by, getRect().getWidth()-5, 5);
+			mGraphRect = LLRect(xleft-5, by, getRect().getWidth()-5, 5);
 			
-			gl_rect_2d(graph_rect, FALSE);
+			gl_rect_2d(mGraphRect, FALSE);
 		}
 		
 		mBarStart.clear();
@@ -813,7 +826,7 @@ void LLFastTimerView::draw()
 		//draw line graph history
 		{
 			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLLocalClipRect clip(graph_rect);
+			LLLocalClipRect clip(mGraphRect);
 			
 			//normalize based on last frame's maximum
 			static U64 last_max = 0;
@@ -830,8 +843,8 @@ void LLFastTimerView::draw()
 			else
 				tdesc = llformat("%4.2f ms", ms);
 							
-			x = graph_rect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5;
-			y = graph_rect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight());
+			x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5;
+			y = mGraphRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight());
  
 			LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white,
 										 LLFontGL::LEFT, LLFontGL::TOP);
@@ -841,24 +854,24 @@ void LLFastTimerView::draw()
 				S32 first_frame = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex;
 				S32 last_frame = first_frame - MAX_VISIBLE_HISTORY;
 				
-				F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1);
+				F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1);
 				
-				F32 right = (F32) graph_rect.mLeft + frame_delta*first_frame;
-				F32 left = (F32) graph_rect.mLeft + frame_delta*last_frame;
+				F32 right = (F32) mGraphRect.mLeft + frame_delta*first_frame;
+				F32 left = (F32) mGraphRect.mLeft + frame_delta*last_frame;
 				
 				gGL.color4f(0.5f,0.5f,0.5f,0.3f);
-				gl_rect_2d((S32) left, graph_rect.mTop, (S32) right, graph_rect.mBottom);
+				gl_rect_2d((S32) left, mGraphRect.mTop, (S32) right, mGraphRect.mBottom);
 				
 				if (mHoverBarIndex >= 0)
 				{
 					S32 bar_frame = first_frame - mHoverBarIndex;
-					F32 bar = (F32) graph_rect.mLeft + frame_delta*bar_frame;
+					F32 bar = (F32) mGraphRect.mLeft + frame_delta*bar_frame;
 
 					gGL.color4f(0.5f,0.5f,0.5f,1);
 				
 					gGL.begin(LLRender::LINES);
-					gGL.vertex2i((S32)bar, graph_rect.mBottom);
-					gGL.vertex2i((S32)bar, graph_rect.mTop);
+					gGL.vertex2i((S32)bar, mGraphRect.mBottom);
+					gGL.vertex2i((S32)bar, mGraphRect.mTop);
 					gGL.end();
 				}
 			}
@@ -883,7 +896,7 @@ void LLFastTimerView::draw()
 				
 				if (mHoverID != NULL &&
 					idp != mHoverID)
-				{	//fade out non-hihglighted timers
+				{	//fade out non-highlighted timers
 					if (idp->getParent() != mHoverID)
 					{
 						alpha = alpha_interp;
@@ -891,8 +904,10 @@ void LLFastTimerView::draw()
 				}
 
 				gGL.color4f(col[0], col[1], col[2], alpha);				
-				gGL.begin(LLRender::LINE_STRIP);
-				for (U32 j = 0; j < LLFastTimer::NamedTimer::HISTORY_NUM; j++)
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				for (U32 j = llmax(0, LLFastTimer::NamedTimer::HISTORY_NUM - LLFastTimer::getLastFrameIndex());
+					j < LLFastTimer::NamedTimer::HISTORY_NUM;
+					j++)
 				{
 					U64 ticks = idp->getHistoricalCount(j);
 
@@ -912,9 +927,10 @@ void LLFastTimerView::draw()
 						//normalize to highlighted timer
 						cur_max = llmax(cur_max, ticks);
 					}
-					F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j;
-					F32 y = graph_rect.mBottom + (F32) graph_rect.getHeight()/max_ticks*ticks;
+					F32 x = mGraphRect.mLeft + ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j;
+					F32 y = mGraphRect.mBottom + (F32) mGraphRect.getHeight()/max_ticks*ticks;
 					gGL.vertex2f(x,y);
+					gGL.vertex2f(x,mGraphRect.mBottom);
 				}
 				gGL.end();
 				
@@ -932,18 +948,20 @@ void LLFastTimerView::draw()
 			}
 			
 			//interpolate towards new maximum
-			F32 dt = gFrameIntervalSeconds*3.f;
-			last_max = (U64) ((F32) last_max + ((F32) cur_max- (F32) last_max) * dt);
+			last_max = (U64) lerp((F32)last_max, (F32) cur_max, LLCriticalDamp::getInterpolant(0.1f));
+			if (last_max - cur_max <= 1 ||  cur_max - last_max  <= 1)
+			{
+				last_max = cur_max;
+			}
 			F32 alpha_target = last_max > cur_max ?
 								llmin((F32) last_max/ (F32) cur_max - 1.f,1.f) :
 								llmin((F32) cur_max/ (F32) last_max - 1.f,1.f);
-			
-			alpha_interp = alpha_interp + (alpha_target-alpha_interp) * dt;
+			alpha_interp = lerp(alpha_interp, alpha_target, LLCriticalDamp::getInterpolant(0.1f));
 
 			if (mHoverID != NULL)
 			{
-				x = (graph_rect.mRight + graph_rect.mLeft)/2;
-				y = graph_rect.mBottom + 8;
+				x = (mGraphRect.mRight + mGraphRect.mLeft)/2;
+				y = mGraphRect.mBottom + 8;
 
 				LLFontGL::getFontMonospace()->renderUTF8(
 					mHoverID->getName(), 
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index ea8251191b29e6a4fd50ca3d16d505aa1364a8e9..a349e7ad4c9324c3e3e8a7f3e5273c872f263c83 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -33,8 +33,9 @@
 class LLFastTimerView : public LLFloater
 {
 public:
-	LLFastTimerView(const LLRect& rect);
-	
+	LLFastTimerView(const LLSD&);
+	BOOL postBuild();
+
 	static BOOL sAnalyzePerformance;
 
 	static void outputAllMetrics();
@@ -44,6 +45,7 @@ class LLFastTimerView : public LLFloater
 	static void doAnalysisDefault(std::string baseline, std::string target, std::string output) ;
 	static LLSD analyzePerformanceLogDefault(std::istream& is) ;
 	static void exportCharts(const std::string& base, const std::string& target);
+	void onPause();
 
 public:
 
@@ -89,6 +91,7 @@ class LLFastTimerView : public LLFloater
 	LLFrameTimer mHighlightTimer;
 	S32 mPrintStats;
 	S32 mAverageCyclesPerTimer;
+	LLRect mGraphRect;
 };
 
 #endif
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index fecc6d91bd81855e89f1f10361067ce19689ed0a..4af5fdd9f36a51eefaca02b8a7dca814808afb74 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -33,6 +33,7 @@
 
 #include "llcompilequeue.h"
 #include "llcallfloater.h"
+#include "llfasttimerview.h"
 #include "llfloaterabout.h"
 #include "llfloateranimpreview.h"
 #include "llfloaterauction.h"
@@ -159,6 +160,7 @@ void LLViewerFloaterReg::registerFloaters()
 	// *NOTE: Please keep these alphabetized for easier merges
 
 	LLFloaterAboutUtil::registerFloater();
+	LLFloaterReg::add("fast_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>);
 	LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>);
 	LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);
 	LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 26599f557e760023213f2941b059cffd2eb38036..754731b290dfd409cc3182b4600c3d0307fcdc17 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -523,7 +523,7 @@ class LLAdvancedToggleConsole : public view_listener_t
 		}
 		else if ("fast timers" == console_type)
 		{
-			toggle_visibility( (void*)gDebugView->mFastTimerView );
+			LLFloaterReg::toggleInstance("fast_timers");
 		}
 		else if ("scene view" == console_type)
 		{
@@ -563,7 +563,7 @@ class LLAdvancedCheckConsole : public view_listener_t
 		}
 		else if ("fast timers" == console_type)
 		{
-			new_value = get_visibility( (void*)gDebugView->mFastTimerView );
+			new_value = LLFloaterReg::instanceVisible("fast_timers");
 		}
 		else if ("scene view" == console_type)
 		{
diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49aa8f384008638e734b0a7bab7ab2f6adeed287
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_close="true"
+ height="500"
+ layout="topleft"
+ name="fast_timers"
+ save_rect="true"
+ save_visibility="false"
+ single_instance="true" 
+ min_width="400"
+ width="700">
+  <string name="pause" >Pause</string>
+  <string name="run">Run</string>
+  <button follows="top|right" 
+          name="pause_btn"
+          left="-200"
+          top="5"
+          width="180"
+          height="40"
+          pad_bottom="-5"
+          label="Pause"
+          font="SansSerifHuge"/>
+</floater>