diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0cb7c7b03039b030416172f67c6b14c14ee4bd62..fb1ef3ff3b83d878c515553190b63c0ae35cddb7 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -97,6 +97,7 @@
 #include "llcallfloater.h"
 #include "llfloatertexturefetchdebugger.h"
 #include "llspellcheck.h"
+#include "llscenemonitor.h"
 
 // Linden library includes
 #include "llavatarnamecache.h"
@@ -1561,6 +1562,14 @@ bool LLAppViewer::cleanup()
 	// workaround for DEV-35406 crash on shutdown
 	LLEventPumps::instance().reset();
 
+	//dump scene loading monitor results
+	if(LLSceneMonitor::getInstance()->hasResults())
+	{
+		std::string file_name = "scene_monitor_results.csv";
+		LLSceneMonitor::getInstance()->dumpToFile(
+			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name));
+	}
+
 	if (LLFastTimerView::sAnalyzePerformance)
 	{
 		llinfos << "Analyzing performance" << llendl;
diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index 0145f6f37efd9d870abfc1379c23723167ef4b40..5cde573855377aeb986ddd647ffc4eebc388e4d6 100644
--- a/indra/newview/llscenemonitor.cpp
+++ b/indra/newview/llscenemonitor.cpp
@@ -486,11 +486,46 @@ void LLSceneMonitor::fetchQueryResult()
 
 	if(mDiffResult > 0.01f)
 	{
-		mRecording->extend();
-		sample(sFramePixelDiff, mDiffResult);
+		addMonitorResult();
 	}
-	//llinfos << count << " : " << mDiffResult << llendl;
 }
+
+void LLSceneMonitor::addMonitorResult()
+{
+	mRecording->extend();
+	sample(sFramePixelDiff, mDiffResult);
+
+	ll_monitor_result_t result;
+	result.mTimeStamp = LLImageGL::sLastFrameTime;
+	result.mDiff = mDiffResult;
+	mMonitorResults.push_back(result);
+}
+
+//dump results to a file _scene_monitor_results.csv
+void LLSceneMonitor::dumpToFile(std::string file_name)
+{
+	if(mMonitorResults.empty())
+	{
+		return; //nothing to dump
+	}
+
+	std::ofstream os(file_name.c_str());
+
+	//total scene loading time
+	os << llformat("Scene Loading time: %.4f seconds\n", (F32)getRecording()->getAcceptedRecording().getDuration().value());
+
+	S32 num_results = mMonitorResults.size();
+	for(S32 i = 0; i < num_results; i++)
+	{
+		os << llformat("%.4f %.4f\n", mMonitorResults[i].mTimeStamp, mMonitorResults[i].mDiff);
+	}
+
+	os.flush();
+	os.close();
+
+	mMonitorResults.clear();
+}
+
 //-------------------------------------------------------------------------------------------------------------
 //definition of class LLSceneMonitorView
 //-------------------------------------------------------------------------------------------------------------
diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h
index 709650e206b5cadfa481df0de4b82ee3f8784a82..b2bc4763cfbaa8d3d231df7fe5eb034a3fae3950 100644
--- a/indra/newview/llscenemonitor.h
+++ b/indra/newview/llscenemonitor.h
@@ -64,6 +64,8 @@ class LLSceneMonitor :  public LLSingleton<LLSceneMonitor>
 	bool needsUpdate() const;
 	
 	LLTrace::ExtendableRecording* getRecording() const {return mRecording;}
+	void dumpToFile(std::string file_name);
+	bool hasResults() const { return !mMonitorResults.empty();}
 
 private:
 	void freezeScene();
@@ -72,6 +74,7 @@ class LLSceneMonitor :  public LLSingleton<LLSceneMonitor>
 	bool preCapture();
 	void generateDitheringTexture(S32 width, S32 height);
 
+	void addMonitorResult();
 private:
 	BOOL mEnabled;
 	BOOL mNeedsUpdateDiff;
@@ -99,6 +102,14 @@ class LLSceneMonitor :  public LLSingleton<LLSceneMonitor>
 	std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
 
 	LLTrace::ExtendableRecording* mRecording;
+
+	//---------------------------------------
+	typedef struct _monitor_result
+	{
+		F32 mTimeStamp;
+		F32 mDiff;
+	} ll_monitor_result_t;
+	std::vector<ll_monitor_result_t> mMonitorResults;
 };
 
 class LLSceneMonitorView : public LLFloater