diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index f03551045ea3a3eac6cae5fd5228d2ad91c2c5d1..b9a9bf1ef0c8c9dd41fbafc6aaad7ac310c9fa14 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -166,7 +166,7 @@ template <class Type> class LLPointer
 };
 
 template<typename Type>
-class LLCopyOnWritePointer
+class LLCopyOnWritePointer : public LLPointer<Type>
 {
 public:
 	typedef LLCopyOnWritePointer<Type> self_t;
@@ -175,43 +175,40 @@ class LLCopyOnWritePointer
 	{}
 
 	LLCopyOnWritePointer(Type* ptr) 
-	:	mPointer(ptr)
+	:	LLPointer(ptr)
 	{}
 
 	LLCopyOnWritePointer(LLPointer<Type>& ptr)
-	:	mPointer(ptr)
+	:	LLPointer(ptr)
 	{}
 
 	Type* write()
 	{
 		makeUnique();
-		return mPointer.get();
+		return mPointer;
 	}
 
 	void makeUnique()
 	{
-		if (mPointer.notNull() && mPointer.get()->getNumRefs() > 1)
+		if (notNull() && mPointer->getNumRefs() > 1)
 		{
-			mPointer = new Type(*mPointer.get());
+			*(LLPointer*)(this) = new Type(*mPointer);
 		}
 	}
+	/*operator BOOL()  const						{ return (mPointer != NULL); }
+	operator bool()  const						{ return (mPointer != NULL); }
+	bool operator!() const						{ return (mPointer == NULL); }
+	bool isNull() const							{ return (mPointer == NULL); }
+	bool notNull() const						{ return (mPointer != NULL); }
 
-	operator BOOL()  const						{ return (BOOL)mPointer; }
-	operator bool()  const						{ return (bool)mPointer; }
-	bool operator!() const						{ return !mPointer; }
-	bool isNull() const							{ return mPointer.isNull(); }
-	bool notNull() const						{ return mPointer.notNull(); }
-
-	bool operator !=(Type* ptr) const           { return (mPointer.get() != ptr); 	}
-	bool operator ==(Type* ptr) const           { return (mPointer.get() == ptr); 	}
+	bool operator !=(Type* ptr) const           { return (mPointer != ptr); 	}
+	bool operator ==(Type* ptr) const           { return (mPointer == ptr); 	}
 	bool operator ==(const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer == ptr.mPointer); 	}
 	bool operator < (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer < ptr.mPointer); 	}
 	bool operator > (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer > ptr.mPointer); 	}
 
-	operator const Type*()   const				{ return mPointer.get(); }
-	const Type*	operator->() const				{ return mPointer.get(); }
-protected:
-	 LLPointer<Type> mPointer;
+	operator const Type*()   const				{ return mPointer; }
+	const Type*	operator->() const				{ return mPointer; }*/
 };
 
 #endif
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 4aa3a5a0f7ca90bfeb5ad9b74a765a4da1dbdae0..cced6546baa3395e5818578eed6e9dc27bd07ed0 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -40,37 +40,31 @@ namespace LLTrace
 ///////////////////////////////////////////////////////////////////////
 
 RecordingBuffers::RecordingBuffers() 
-:	mCountsFloat(new AccumulatorBuffer<CountAccumulator<F64> >()),
-	mMeasurementsFloat(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
-	mCounts(new AccumulatorBuffer<CountAccumulator<S64> >()),
-	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<S64> >()),
-	mStackTimers(new AccumulatorBuffer<TimeBlockAccumulator>()),
-	mMemStats(new AccumulatorBuffer<MemStatAccumulator>())
 {}
 
 void RecordingBuffers::handOffTo(RecordingBuffers& other)
 {
-	other.mCountsFloat.write()->reset(mCountsFloat);
-	other.mMeasurementsFloat.write()->reset(mMeasurementsFloat);
-	other.mCounts.write()->reset(mCounts);
-	other.mMeasurements.write()->reset(mMeasurements);
-	other.mStackTimers.write()->reset(mStackTimers);
-	other.mMemStats.write()->reset(mMemStats);
+	other.mCountsFloat.reset(&mCountsFloat);
+	other.mMeasurementsFloat.reset(&mMeasurementsFloat);
+	other.mCounts.reset(&mCounts);
+	other.mMeasurements.reset(&mMeasurements);
+	other.mStackTimers.reset(&mStackTimers);
+	other.mMemStats.reset(&mMemStats);
 }
 
 void RecordingBuffers::makePrimary()
 {
-	mCountsFloat.write()->makePrimary();
-	mMeasurementsFloat.write()->makePrimary();
-	mCounts.write()->makePrimary();
-	mMeasurements.write()->makePrimary();
-	mStackTimers.write()->makePrimary();
-	mMemStats.write()->makePrimary();
+	mCountsFloat.makePrimary();
+	mMeasurementsFloat.makePrimary();
+	mCounts.makePrimary();
+	mMeasurements.makePrimary();
+	mStackTimers.makePrimary();
+	mMemStats.makePrimary();
 
 	ThreadRecorder* thread_recorder = get_thread_recorder().get();
-	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = *mStackTimers.write();
+	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
 	// update stacktimer parent pointers
-	for (S32 i = 0, end_i = mStackTimers->size(); i < end_i; i++)
+	for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
 	{
 		TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
 		if (tree_node)
@@ -82,46 +76,36 @@ void RecordingBuffers::makePrimary()
 
 bool RecordingBuffers::isPrimary() const
 {
-	return mCounts->isPrimary();
+	return mCounts.isPrimary();
 }
 
-void RecordingBuffers::makeUnique()
+void RecordingBuffers::append( const RecordingBuffers& other )
 {
-	mCountsFloat.makeUnique();
-	mMeasurementsFloat.makeUnique();
-	mCounts.makeUnique();
-	mMeasurements.makeUnique();
-	mStackTimers.makeUnique();
-	mMemStats.makeUnique();
+	mCountsFloat.addSamples(other.mCountsFloat);
+	mMeasurementsFloat.addSamples(other.mMeasurementsFloat);
+	mCounts.addSamples(other.mCounts);
+	mMeasurements.addSamples(other.mMeasurements);
+	mMemStats.addSamples(other.mMemStats);
+	mStackTimers.addSamples(other.mStackTimers);
 }
 
-void RecordingBuffers::appendBuffers( const RecordingBuffers& other )
+void RecordingBuffers::merge( const RecordingBuffers& other)
 {
-	mCountsFloat.write()->addSamples(*other.mCountsFloat);
-	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
-	mCounts.write()->addSamples(*other.mCounts);
-	mMeasurements.write()->addSamples(*other.mMeasurements);
-	mMemStats.write()->addSamples(*other.mMemStats);
-	mStackTimers.write()->addSamples(*other.mStackTimers);
+	mCountsFloat.addSamples(other.mCountsFloat);
+	mMeasurementsFloat.addSamples(other.mMeasurementsFloat);
+	mCounts.addSamples(other.mCounts);
+	mMeasurements.addSamples(other.mMeasurements);
+	mMemStats.addSamples(other.mMemStats);
 }
 
-void RecordingBuffers::mergeBuffers( const RecordingBuffers& other)
+void RecordingBuffers::reset(RecordingBuffers* other)
 {
-	mCountsFloat.write()->addSamples(*other.mCountsFloat);
-	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
-	mCounts.write()->addSamples(*other.mCounts);
-	mMeasurements.write()->addSamples(*other.mMeasurements);
-	mMemStats.write()->addSamples(*other.mMemStats);
-}
-
-void RecordingBuffers::resetBuffers(RecordingBuffers* other)
-{
-	mCountsFloat.write()->reset(other ? other->mCountsFloat : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >());
-	mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >());
-	mCounts.write()->reset(other ? other->mCounts : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >());
-	mMeasurements.write()->reset(other ? other->mMeasurements : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >());
-	mStackTimers.write()->reset(other ? other->mStackTimers : LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >());
-	mMemStats.write()->reset(other ? other->mMemStats : LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >());
+	mCountsFloat.reset(other ? &other->mCountsFloat : NULL);
+	mMeasurementsFloat.reset(other ? &other->mMeasurementsFloat : NULL);
+	mCounts.reset(other ? &other->mCounts : NULL);
+	mMeasurements.reset(other ? &other->mMeasurements : NULL);
+	mStackTimers.reset(other ? &other->mStackTimers : NULL);
+	mMemStats.reset(other ? &other->mMemStats : NULL);
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -130,22 +114,24 @@ void RecordingBuffers::resetBuffers(RecordingBuffers* other)
 
 Recording::Recording() 
 :	mElapsedSeconds(0)
-{}
+{
+	mBuffers = new RecordingBuffers();
+}
 
 Recording::Recording( const Recording& other )
-:	mSamplingTimer(other.mSamplingTimer)
 {
 	Recording& mutable_other = const_cast<Recording&>(other);
 	EPlayState other_play_state = other.getPlayState();
 	mutable_other.pause();
 
-	appendBuffers(other);
+	mBuffers = other.mBuffers;
 
 	LLStopWatchControlsMixin<Recording>::setPlayState(other_play_state);
 	mutable_other.setPlayState(other_play_state);
 
 	// above call will clear mElapsedSeconds as a side effect, so copy it here
 	mElapsedSeconds = other.mElapsedSeconds;
+	mSamplingTimer = other.mSamplingTimer;
 }
 
 
@@ -166,7 +152,7 @@ void Recording::update()
 
 void Recording::handleReset()
 {
-	resetBuffers();
+	mBuffers.write()->reset();
 
 	mElapsedSeconds = 0.0;
 	mSamplingTimer.reset();
@@ -187,42 +173,42 @@ void Recording::handleStop()
 
 void Recording::handleSplitTo(Recording& other)
 {
-	handOffTo(other);
+	mBuffers.write()->handOffTo(*other.mBuffers.write());
 }
 
 void Recording::appendRecording( const Recording& other )
 {
-	appendBuffers(other);
+	mBuffers.write()->append(*other.mBuffers);
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
 void Recording::mergeRecording( const Recording& other)
 {
-	mergeBuffers(other);
+	mBuffers.write()->merge(*other.mBuffers);
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
 U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
 {
-	return (*mStackTimers)[stat.getIndex()].mCalls;
+	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
@@ -230,7 +216,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return (F64)(accumulator.mSelfTimeCounter) 
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
@@ -238,45 +224,45 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 
 F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
 {
-	return (F32)(*mStackTimers)[stat.getIndex()].mCalls / mElapsedSeconds;
+	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds;
 }
 
 LLUnit<LLUnits::Bytes, U32> Recording::getSum(const TraceType<MemStatAccumulator>& stat) const
 {
-	return (*mMemStats)[stat.getIndex()].mAllocatedCount;
+	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
 }
 
 LLUnit<LLUnits::Bytes, F32> Recording::getPerSec(const TraceType<MemStatAccumulator>& stat) const
 {
-	return (F32)(*mMemStats)[stat.getIndex()].mAllocatedCount / mElapsedSeconds;
+	return (F32)mBuffers->mMemStats[stat.getIndex()].mAllocatedCount / mElapsedSeconds;
 }
 
 
 F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	return (*mCountsFloat)[stat.getIndex()].getSum();
+	return mBuffers->mCountsFloat[stat.getIndex()].getSum();
 }
 
 S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	return (*mCounts)[stat.getIndex()].getSum();
+	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
 F64 Recording::getSum( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (F64)(*mMeasurementsFloat)[stat.getIndex()].getSum();
+	return (F64)mBuffers->mMeasurementsFloat[stat.getIndex()].getSum();
 }
 
 S64 Recording::getSum( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (S64)(*mMeasurements)[stat.getIndex()].getSum();
+	return (S64)mBuffers->mMeasurements[stat.getIndex()].getSum();
 }
 
 
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	F64 sum = (*mCountsFloat)[stat.getIndex()].getSum();
+	F64 sum = mBuffers->mCountsFloat[stat.getIndex()].getSum();
 	return  (sum != 0.0) 
 		? (sum / mElapsedSeconds)
 		: 0.0;
@@ -284,7 +270,7 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	S64 sum = (*mCounts)[stat.getIndex()].getSum();
+	S64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return (sum != 0) 
 		? ((F64)sum / mElapsedSeconds)
 		: 0.0;
@@ -292,72 +278,72 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	return (*mCountsFloat)[stat.getIndex()].getSampleCount();
+	return mBuffers->mCountsFloat[stat.getIndex()].getSampleCount();
 }
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getSampleCount();
 }
 
 F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getMin();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMin();
 }
 
 S64 Recording::getMin( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getMin();
+	return mBuffers->mMeasurements[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getMax();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMax();
 }
 
 S64 Recording::getMax( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getMax();
+	return mBuffers->mMeasurements[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getMean();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMean();
 }
 
 F64 Recording::getMean( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getMean();
+	return mBuffers->mMeasurements[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getStandardDeviation();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getStandardDeviation();
+	return mBuffers->mMeasurements[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getLastValue();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getLastValue();
 }
 
 S64 Recording::getLastValue( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getLastValue();
+	return mBuffers->mMeasurements[stat.getIndex()].getLastValue();
 }
 
 U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getSampleCount();
 }
 
 U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getSampleCount();
+	return mBuffers->mMeasurements[stat.getIndex()].getSampleCount();
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -366,16 +352,9 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st
 
 PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) 
 :	mAutoResize(num_periods == 0),
-	mCurPeriod(0)
+	mCurPeriod(0),
+	mRecordingPeriods(num_periods ? num_periods : 1)
 {
-	if (mAutoResize) 
-	{
-		num_periods = 1;
-	}
-	if (num_periods)
-	{
-		mRecordingPeriods.resize(num_periods);
-	}
 	setPlayState(state);
 }
 
@@ -552,7 +531,7 @@ void PeriodicRecording::handleReset()
 
 void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 {
-	getCurRecording().handOffTo(other.getCurRecording());
+	getCurRecording().splitTo(other.getCurRecording());
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -589,7 +568,7 @@ void ExtendableRecording::handleReset()
 
 void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
 {
-	mPotentialRecording.handOffTo(other.mPotentialRecording);
+	mPotentialRecording.splitTo(other.mPotentialRecording);
 }
 
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index be8618a2990976cf2475818bcc03390e2b3f1c5d..b339e72e5cc5462606f1235e0026970ca817312a 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -106,33 +106,28 @@ class LLStopWatchControlsMixin
 
 namespace LLTrace
 {
-	class RecordingBuffers
+	struct RecordingBuffers : public LLRefCount
 	{
-	public:
 		RecordingBuffers();
 
 		void handOffTo(RecordingBuffers& other);
 		void makePrimary();
 		bool isPrimary() const;
 
-		void makeUnique();
-
-		void appendBuffers(const RecordingBuffers& other);
-		void mergeBuffers(const RecordingBuffers& other);
-		void resetBuffers(RecordingBuffers* other = NULL);
+		void append(const RecordingBuffers& other);
+		void merge(const RecordingBuffers& other);
+		void reset(RecordingBuffers* other = NULL);
 
-	protected:
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCountsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >			mStackTimers;
-		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
+		AccumulatorBuffer<CountAccumulator<F64> > 		mCountsFloat;
+		AccumulatorBuffer<MeasurementAccumulator<F64> > mMeasurementsFloat;
+		AccumulatorBuffer<CountAccumulator<S64> > 		mCounts;
+		AccumulatorBuffer<MeasurementAccumulator<S64> > mMeasurements;
+		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers;
+		AccumulatorBuffer<MemStatAccumulator> 			mMemStats;
 	};
 
 	class Recording 
-	:	public LLStopWatchControlsMixin<Recording>, 
-		public RecordingBuffers
+	:	public LLStopWatchControlsMixin<Recording>
 	{
 	public:
 		Recording();
@@ -149,6 +144,9 @@ namespace LLTrace
 		// grab latest recorded data
 		void update();
 
+		// ensure that buffers are exclusively owned by this recording
+		void makeUnique() { mBuffers.makeUnique(); }
+
 		// Timer accessors
 		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat) const;
 		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const;
@@ -237,7 +235,7 @@ namespace LLTrace
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
-	private:
+	protected:
 		friend class ThreadRecorder;
 
 		// implementation for LLStopWatchControlsMixin
@@ -249,8 +247,9 @@ namespace LLTrace
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
-		LLTimer			mSamplingTimer;
-		F64				mElapsedSeconds;
+		LLTimer				mSamplingTimer;
+		F64					mElapsedSeconds;
+		LLCopyOnWritePointer<RecordingBuffers>	mBuffers;
 	};
 
 	class LL_COMMON_API PeriodicRecording
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 9bef040cf7b1ce27d36da39c1670d2f85cc0e28a..2001b9cd7f4813fd3a1f4d072786ea8b4f4c7a3c 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -118,7 +118,7 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Record
 		if (next_it != mActiveRecordings.end())
 		{
 			// ...push our gathered data down to it
-			(*next_it)->mPartialRecording.appendBuffers((*it)->mPartialRecording);
+			(*next_it)->mPartialRecording.append((*it)->mPartialRecording);
 		}
 
 		// copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
@@ -156,7 +156,7 @@ void ThreadRecorder::deactivate( Recording* recording )
 		++next_it;
 		if (next_it != mActiveRecordings.end())
 		{
-			(*next_it)->mTargetRecording->makePrimary();
+			(*next_it)->mTargetRecording->mBuffers.write()->makePrimary();
 		}
 
 		delete *it;
@@ -171,8 +171,8 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
 
 void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 {
-	mTargetRecording->appendBuffers(mPartialRecording);
-	mPartialRecording.resetBuffers();
+	mTargetRecording->mBuffers.write()->append(mPartialRecording);
+	mPartialRecording.reset();
 }
 
 
@@ -203,31 +203,31 @@ void SlaveThreadRecorder::pushToMaster()
 void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.appendRecording(source);
+	appendRecording(source);
 }
 
 void SlaveThreadRecorder::SharedData::appendTo( Recording& sink )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	sink.appendRecording(mRecording);
+	sink.appendRecording(*this);
 }
 
 void SlaveThreadRecorder::SharedData::mergeFrom( const RecordingBuffers& source )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.mergeBuffers(source);
+	mBuffers.write()->merge(source);
 }
 
 void SlaveThreadRecorder::SharedData::mergeTo( RecordingBuffers& sink )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	sink.mergeBuffers(mRecording);
+	sink.merge(*mBuffers);
 }
 
 void SlaveThreadRecorder::SharedData::reset()
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.reset();
+	Recording::reset();
 }
 
 
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 3e24303d92fe33bc42023f71d15c3da6f92fb568..c44bcbd12d139ef3faad2068dab97a8587ee2ee0 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -106,7 +106,7 @@ namespace LLTrace
 
 		MasterThreadRecorder* 	mMaster;
 
-		class SharedData
+		class SharedData : public Recording
 		{
 		public:
 			void appendFrom(const Recording& source);
@@ -116,7 +116,6 @@ namespace LLTrace
 			void reset();
 		private:
 			LLMutex		mRecordingMutex;
-			Recording	mRecording;
 		};
 		SharedData		mSharedData;
 	};
diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index b7517a057e6ac477ee9d1ab446ee25daed34298d..b303dfbdb430019793a42c6e668bb4441c1175b8 100644
--- a/indra/newview/llscenemonitor.cpp
+++ b/indra/newview/llscenemonitor.cpp
@@ -270,10 +270,12 @@ void LLSceneMonitor::capture()
 	static LLFrameTimer timer;	
 
 	LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording();
-	if (last_frame_recording.getSum(*LLViewerCamera::getVelocityStat()) > 0.001f
-		|| last_frame_recording.getSum(*LLViewerCamera::getAngularVelocityStat()) > 0.01f)
+	if (mEnabled 
+		&&	(last_frame_recording.getSum(*LLViewerCamera::getVelocityStat()) > 0.001f
+			|| last_frame_recording.getSum(*LLViewerCamera::getAngularVelocityStat()) > 0.01f))
 	{
 		reset();
+		freezeScene();
 	}
 
 	bool enabled = monitor_enabled || mDebugViewerVisible;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 002f0c7aa3c998bce3eb4553f37ccb1903b0a1b3..e8196e965578755a06cf77dd4cd54c974394924f 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -64,7 +64,7 @@
 namespace LLStatViewer
 {
 
-LLTrace::CountStatHandle<>	FPS("fpsstat"),
+LLTrace::CountStatHandle<>	FPS("framesrendered"),
 							PACKETS_IN("packetsinstat"),
 							PACKETS_LOST("packetsloststat"),
 							PACKETS_OUT("packetsoutstat"),
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
index f98fcc349e90120bee032f45b41fa846c2d78ac7..0493f487d45359533ec0eeb7555b66d7e50528ef 100644
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -38,7 +38,7 @@
 			   name="fps"
 			   label="FPS"
 			   unit_label="fps"
-			   stat="fpsstat"
+			   stat="framesrendered"
 			   bar_min="0"
 			   bar_max="60"
 			   tick_spacing="6"