diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 4e5fdb1219dbf0a2444daf1738be5d74329803cc..72d51540ef149f9796adb140838af630330a9dd8 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3406,6 +3406,9 @@ void LLAgent::setTeleportState(ETeleportState state)
 	}
 	else if(mTeleportState == TELEPORT_ARRIVING)
 	{
+		// First two position updates after a teleport tend to be weird
+		LLViewerStats::getInstance()->mAgentPositionSnaps.mCountOfNextUpdatesToIgnore = 2;
+
 		// Let the interested parties know we've teleported.
 		LLViewerParcelMgr::getInstance()->onTeleportFinished(false, getPositionGlobal());
 	}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 6d93de23837df9c9d9daf5e79d9cf82780ac8e62..15bdf126c532ae0705ea11fd034502499dd780b1 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -79,6 +79,7 @@
 #include "llviewerparceloverlay.h"
 #include "llviewerpartsource.h"
 #include "llviewerregion.h"
+#include "llviewerstats.h"
 #include "llviewertextureanim.h"
 #include "llviewerwindow.h" // For getSpinAxis
 #include "llvoavatar.h"
@@ -1916,6 +1917,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 
 			avatar->clampAttachmentPositions();
 		}
+		
+		// If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps
+		if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) )
+		{
+			LLViewerStats::getInstance()->mAgentPositionSnaps.push( diff.length() );
+		}
 	}
 
 	if (new_rot != mLastRot
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index bdc34d0f18dd310f20d69ca1d8dc5c745c85fd39..a706e77f195a2aae1601cdef1556ba96962eb6be 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -280,6 +280,8 @@ LLViewerStats::LLViewerStats() :
 	{
 		mStats[ST_HAS_BAD_TIMER] = 1.0;
 	}	
+	
+	mAgentPositionSnaps.reset();
 }
 
 LLViewerStats::~LLViewerStats()
@@ -299,6 +301,8 @@ void LLViewerStats::resetStats()
 	LLViewerStats::getInstance()->mPacketsOutStat.reset();
 	LLViewerStats::getInstance()->mFPSStat.reset();
 	LLViewerStats::getInstance()->mTexturePacketsStat.reset();
+	
+	LLViewerStats::getInstance()->mAgentPositionSnaps.reset();
 }
 
 
@@ -393,6 +397,10 @@ void LLViewerStats::addToMessage(LLSD &body) const
 					<< llendl;
 		}
 	}
+	
+	body["AgentPositionSnaps"] = mAgentPositionSnaps.getData();
+	llinfos << "STAT: AgentPositionSnaps: Mean = " << mAgentPositionSnaps.getMean() << "; StdDev = " << mAgentPositionSnaps.getStdDev() 
+			<< "; Count = " << mAgentPositionSnaps.getCount() << llendl;
 }
 
 // static
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 13d73000d242ed6158e38821d8437bf94b2a7141..b5cea9d6a80bcc7028626be47bdc68e6596610f8 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -197,6 +197,60 @@ class LLViewerStats : public LLSingleton<LLViewerStats>
 	
 	void addToMessage(LLSD &body) const;
 
+	struct  StatsAccumulator
+	{
+		S32 mCount;
+		F32 mSum;
+		F32 mSumOfSquares;
+		U32 mCountOfNextUpdatesToIgnore;
+
+		inline void push( F32 val )
+		{
+			if ( mCountOfNextUpdatesToIgnore > 0 )
+			{
+				mCountOfNextUpdatesToIgnore--;
+				return;
+			}
+			
+			mCount++;
+			mSum += val;
+			mSumOfSquares += val * val;
+		}
+		
+		inline F32 getMean() const
+		{
+			return (mCount == 0) ? 0.f : ((F32)mSum)/mCount;
+		}
+		
+		inline F32 getStdDev() const
+		{
+			const F32 mean = getMean();
+			return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) );
+		}
+		
+		inline U32 getCount() const
+		{
+			return mCount;
+		}
+
+		inline void reset()
+		{
+			mCount = mSum = mSumOfSquares = 0;
+			mCountOfNextUpdatesToIgnore = 0;
+		}
+		
+		inline LLSD getData() const
+		{
+			LLSD data;
+			data["mean"] = getMean();
+			data["std_dev"] = getStdDev();
+			data["count"] = (S32)mCount;
+			return data;
+		}
+	};
+
+	StatsAccumulator mAgentPositionSnaps;
+	
 private:
 	F64	mStats[ST_COUNT];