From 40979589afc5c91cab977307a1e400315b1c8a8f Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 27 Oct 2010 23:15:22 -0700
Subject: [PATCH] STORM-105 : improve decompression perf gathering, allow perf
 name to be passed on the command line, fix crash in analysis phase

---
 indra/llcommon/llfasttimer_class.cpp    |  1 +
 indra/llcommon/llfasttimer_class.h      |  1 +
 indra/llimage/llimagej2c.cpp            | 80 ++++++++++++++++++-------
 indra/llimage/llimagej2c.h              |  4 +-
 indra/newview/app_settings/cmd_line.xml |  2 +
 indra/newview/llappviewer.cpp           | 52 ++++++++--------
 indra/newview/llappviewer.h             |  4 +-
 indra/newview/llfasttimerview.cpp       | 25 ++++++--
 indra/newview/llviewertexture.cpp       |  6 +-
 9 files changed, 118 insertions(+), 57 deletions(-)

diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
index c45921cdec8..bce87ada969 100644
--- a/indra/llcommon/llfasttimer_class.cpp
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -56,6 +56,7 @@ bool LLFastTimer::sPauseHistory = 0;
 bool LLFastTimer::sResetHistory = 0;
 LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
 BOOL LLFastTimer::sLog = FALSE;
+std::string LLFastTimer::sLogName = "";
 BOOL LLFastTimer::sMetricLog = FALSE;
 LLMutex* LLFastTimer::sLogLock = NULL;
 std::queue<LLSD> LLFastTimer::sLogQueue;
diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h
index 1158ac5140a..eb9789682bb 100644
--- a/indra/llcommon/llfasttimer_class.h
+++ b/indra/llcommon/llfasttimer_class.h
@@ -211,6 +211,7 @@ class LL_COMMON_API LLFastTimer
 	static std::queue<LLSD> sLogQueue;
 	static BOOL				sLog;
 	static BOOL				sMetricLog;
+	static std::string		sLogName;
 	static bool 			sPauseHistory;
 	static bool 			sResetHistory;
 	static U64				sTimerCycles;
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 207728d4d92..08a5912c576 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -31,6 +31,7 @@
 #include "llimagej2c.h"
 #include "llmemtype.h"
 #include "lltimer.h"
+#include "llmath.h"
 
 typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
 typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
@@ -54,6 +55,7 @@ const char* fallbackEngineInfoLLImageJ2CImpl();
 
 // Test data gathering handle
 LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ;
+const std::string sTesterName("ImageCompressionTester");
 
 //static
 //Loads the required "create", "destroy" and "engineinfo" functions needed
@@ -200,7 +202,7 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 		mDataSizes[i] = 0;
 	}
 
-	if (LLFastTimer::sMetricLog && !LLImageJ2C::sTesterp)
+	if (LLFastTimer::sMetricLog && !LLImageJ2C::sTesterp && ((LLFastTimer::sLogName == sTesterName) || (LLFastTimer::sLogName == "metric")))
 	{
 		LLImageJ2C::sTesterp = new LLImageCompressionTester() ;
         if (!LLImageJ2C::sTesterp->isValid())
@@ -590,16 +592,23 @@ LLImageJ2CImpl::~LLImageJ2CImpl()
 //----------------------------------------------------------------------------------------------
 // Start of LLImageCompressionTester
 //----------------------------------------------------------------------------------------------
-LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTesterBasic("ImageCompressionTester") 
+LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTesterBasic(sTesterName) 
 {
+	addMetric("TotalTimeDecompression");
 	addMetric("TotalBytesInDecompression");
 	addMetric("TotalBytesOutDecompression");
+	addMetric("RateDecompression");
+	addMetric("PerfDecompression");
+
+	addMetric("TotalTimeCompression");
 	addMetric("TotalBytesInCompression");
 	addMetric("TotalBytesOutCompression");
-    
-	addMetric("TimeTimeDecompression");
-	addMetric("TimeTimeCompression");
-	
+	addMetric("RateCompression");
+	addMetric("PerfCompression");
+
+	mRunBytesInDecompression = 0;
+    mRunBytesInCompression = 0;
+
     mTotalBytesInDecompression = 0;
     mTotalBytesOutDecompression = 0;
     mTotalBytesInCompression = 0;
@@ -618,13 +627,40 @@ LLImageCompressionTester::~LLImageCompressionTester()
 void LLImageCompressionTester::outputTestRecord(LLSD *sd) 
 {	
     std::string currentLabel = getCurrentLabelName();
-	(*sd)[currentLabel]["TotalBytesInDecompression"]   = (LLSD::Integer)mTotalBytesInDecompression;
-	(*sd)[currentLabel]["TotalBytesOutDecompression"]  = (LLSD::Integer)mTotalBytesOutDecompression;
-	(*sd)[currentLabel]["TotalBytesInCompression"]     = (LLSD::Integer)mTotalBytesInCompression;
-	(*sd)[currentLabel]["TotalBytesOutCompression"]    = (LLSD::Integer)mTotalBytesOutCompression;
-    
-	(*sd)[currentLabel]["TimeTimeDecompression"]       = (LLSD::Real)mTotalTimeDecompression;
-	(*sd)[currentLabel]["TimeTimeCompression"]         = (LLSD::Real)mTotalTimeCompression;
+	
+	F32 decompressionPerf = 0.0f;
+	F32 compressionPerf = 0.0f;
+	F32 decompressionRate = 0.0f;
+	F32 compressionRate = 0.0f;
+	
+	if (!is_approx_zero(mTotalTimeDecompression))
+	{
+		decompressionPerf = (F32)(mTotalBytesInDecompression) / mTotalTimeDecompression;
+	}
+	if (mTotalBytesOutDecompression > 0)
+	{
+		decompressionRate = (F32)(mTotalBytesInDecompression) / (F32)(mTotalBytesOutDecompression);
+	}
+	if (!is_approx_zero(mTotalTimeCompression))
+	{
+		compressionPerf = (F32)(mTotalBytesInCompression) / mTotalTimeCompression;
+	}
+	if (mTotalBytesOutCompression > 0)
+	{
+		compressionRate = (F32)(mTotalBytesInCompression) / (F32)(mTotalBytesOutCompression);
+	}
+	
+	(*sd)[currentLabel]["TotalTimeDecompression"]		= (LLSD::Real)mTotalTimeDecompression;
+	(*sd)[currentLabel]["TotalBytesInDecompression"]	= (LLSD::Integer)mTotalBytesInDecompression;
+	(*sd)[currentLabel]["TotalBytesOutDecompression"]	= (LLSD::Integer)mTotalBytesOutDecompression;
+	(*sd)[currentLabel]["RateDecompression"]			= (LLSD::Real)decompressionRate;
+	(*sd)[currentLabel]["PerfDecompression"]			= (LLSD::Real)decompressionPerf;
+	
+	(*sd)[currentLabel]["TotalTimeCompression"]			= (LLSD::Real)mTotalTimeCompression;
+	(*sd)[currentLabel]["TotalBytesInCompression"]		= (LLSD::Integer)mTotalBytesInCompression;
+	(*sd)[currentLabel]["TotalBytesOutCompression"]		= (LLSD::Integer)mTotalBytesOutCompression;
+    (*sd)[currentLabel]["RateCompression"]				= (LLSD::Real)compressionRate;
+	(*sd)[currentLabel]["PerfCompression"]				= (LLSD::Real)compressionPerf;
 }
 
 void LLImageCompressionTester::updateCompressionStats(const F32 deltaTime) 
@@ -635,15 +671,14 @@ void LLImageCompressionTester::updateCompressionStats(const F32 deltaTime)
 void LLImageCompressionTester::updateCompressionStats(const S32 bytesCompress, const S32 bytesRaw) 
 {
     mTotalBytesInCompression += bytesRaw;
+    mRunBytesInCompression += bytesRaw;
     mTotalBytesOutCompression += bytesCompress;
-    if (mTotalBytesInCompression > (1000000))
+    if (mRunBytesInCompression > (1000000))
     {
         // Output everything
         outputTestResults();
-        // Reset only the compression data
-        mTotalBytesInCompression = 0;
-        mTotalBytesOutCompression = 0;
-        mTotalTimeCompression = 0.0f;
+        // Reset the compression data of the run
+        mRunBytesInCompression = 0;
     }
 }
 
@@ -655,15 +690,14 @@ void LLImageCompressionTester::updateDecompressionStats(const F32 deltaTime)
 void LLImageCompressionTester::updateDecompressionStats(const S32 bytesIn, const S32 bytesOut) 
 {
     mTotalBytesInDecompression += bytesIn;
+    mRunBytesInDecompression += bytesIn;
     mTotalBytesOutDecompression += bytesOut;
-    if (mTotalBytesInDecompression > (5*1000000))
+    if (mRunBytesInDecompression > (1000000))
     {
         // Output everything
         outputTestResults();
-        // Reset only the decompression data
-        mTotalBytesInDecompression = 0;
-        mTotalBytesOutDecompression = 0;
-        mTotalTimeDecompression = 0.0f;
+        // Reset the decompression data of the run
+        mRunBytesInDecompression = 0;
     }
 }
 
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index adbfb9cdb34..3933c9236f2 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -127,7 +127,7 @@ class LLImageJ2CImpl
 //
 // This class is used for performance data gathering only.
 // Tracks the image compression / decompression data,
-// records and outputs them to metric.slp log files.
+// records and outputs them to the log file.
 //
 class LLImageCompressionTester : public LLMetricPerformanceTesterBasic
 {
@@ -151,6 +151,8 @@ class LLImageCompressionTester : public LLMetricPerformanceTesterBasic
         U32 mTotalBytesOutDecompression;    // Total bytes produced by decompressor
         U32 mTotalBytesInCompression;       // Total bytes fed to compressor
         U32 mTotalBytesOutCompression;      // Total bytes produced by compressor
+		U32 mRunBytesInDecompression;		// Bytes fed to decompressor in this run
+		U32 mRunBytesInCompression;			// Bytes fed to compressor in this run
         //
         // Time
         //
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 00d69f805e8..5ab07af5aa8 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -118,6 +118,8 @@
     <map>
       <key>desc</key>
       <string>Log metrics for benchmarking</string>
+      <key>count</key>
+      <integer>1</integer>
       <key>map-to</key>
       <string>LogMetrics</string>
     </map>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 974ea6b4ae1..cfc38f41b97 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -510,16 +510,10 @@ class LLFastTimerLogThread : public LLThread
 public:
 	std::string mFile;
 
-	LLFastTimerLogThread() : LLThread("fast timer log")
+	LLFastTimerLogThread(std::string& testName) : LLThread("fast timer log")
 	{
-		if(LLFastTimer::sLog)
-		{
-			mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp");
-		}
-		if(LLFastTimer::sMetricLog)
-		{
-			mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp");
-		}
+		std::string fileName = testName + std::string(".slp");
+		mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, fileName);
 	}
 
 	void run()
@@ -1616,20 +1610,14 @@ bool LLAppViewer::cleanup()
 	{
 		llinfos << "Analyzing performance" << llendl;
 		
-		if(LLFastTimer::sLog)
-		{
-			LLFastTimerView::doAnalysis(
-				gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_baseline.slp"),
-				gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp"),
-				gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_report.csv"));
-		}
-		if(LLFastTimer::sMetricLog)
-		{
-			LLFastTimerView::doAnalysis(
-				gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_baseline.slp"),
-				gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp"),
-				gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_report.csv"));
-		}
+		std::string baselineName = LLFastTimer::sLogName + "_baseline.slp";
+		std::string currentName  = LLFastTimer::sLogName + ".slp"; 
+		std::string reportName   = LLFastTimer::sLogName + "_report.csv";
+		
+		LLFastTimerView::doAnalysis(
+			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baselineName),
+			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, currentName),
+			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, reportName));
 	}
 	LLMetricPerformanceTesterBasic::cleanClass() ;
 
@@ -1738,7 +1726,7 @@ bool LLAppViewer::initThreads()
 	if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
 	{
 		LLFastTimer::sLogLock = new LLMutex(NULL);
-		mFastTimerLogThread = new LLFastTimerLogThread();
+		mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
 		mFastTimerLogThread->start();
 	}
 
@@ -2080,11 +2068,25 @@ bool LLAppViewer::initConfiguration()
 	if (clp.hasOption("logperformance"))
 	{
 		LLFastTimer::sLog = TRUE;
+		LLFastTimer::sLogName = std::string("performance");
 	}
 	
-	if(clp.hasOption("logmetrics"))
+	if (clp.hasOption("logmetrics"))
 	{
 		LLFastTimer::sMetricLog = TRUE ;
+		// '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test
+		// In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...)
+        std::string testName = clp.getOption("logmetrics")[0];
+		llinfos << "'--logmetrics' argument : " << testName << llendl;
+        if (testName == "")
+        {
+            llwarns << "No '--logmetrics' argument given, will output all metrics." << llendl;
+			LLFastTimer::sLogName = std::string("metric");
+        }
+        else
+        {
+			LLFastTimer::sLogName = testName;
+		}
 	}
 
 	if (clp.hasOption("graphicslevel"))
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index fdc3b9ef9e9..6421f3fd6fe 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -167,7 +167,7 @@ class LLAppViewer : public LLApp
 	// mute/unmute the system's master audio
 	virtual void setMasterSystemAudioMute(bool mute);
 	virtual bool getMasterSystemAudioMute();
-	
+
 protected:
 	virtual bool initWindow(); // Initialize the viewer's window.
 	virtual bool initLogging(); // Initialize log files, logging system, return false on failure.
@@ -251,7 +251,9 @@ class LLAppViewer : public LLApp
 
 	LLWatchdogTimeout* mMainloopTimeout;
 
+	// For performance and metric gathering
 	LLThread*	mFastTimerLogThread;
+	
 	// for tracking viewer<->region circuit death
 	bool mAgentRegionLastAlive;
 	LLUUID mAgentRegionLastID;
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 06b145e8c8b..5b6a25a0413 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -1086,14 +1086,22 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
 //static
 void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target, std::string output)
 {
+	// Open baseline and current target, exit if one is inexistent
+	std::ifstream base_is(baseline.c_str());
+	std::ifstream target_is(target.c_str());
+	if (!base_is.is_open() || !target_is.is_open())
+	{
+		llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
+		base_is.close();
+		target_is.close();
+		return;
+	}
 
 	//analyze baseline
-	std::ifstream base_is(baseline.c_str());
 	LLSD base = analyzePerformanceLogDefault(base_is);
 	base_is.close();
 
 	//analyze current
-	std::ifstream target_is(target.c_str());
 	LLSD current = analyzePerformanceLogDefault(target_is);
 	target_is.close();
 
@@ -1193,13 +1201,22 @@ void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target
 		return ;
 	}
 
-	//analyze baseline
+	// Open baseline and current target, exit if one is inexistent
 	std::ifstream base_is(baseline.c_str());
+	std::ifstream target_is(target.c_str());
+	if (!base_is.is_open() || !target_is.is_open())
+	{
+		llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
+		base_is.close();
+		target_is.close();
+		return;
+	}
+
+	//analyze baseline
 	LLSD base = analyzeMetricPerformanceLog(base_is);
 	base_is.close();
 
 	//analyze current
-	std::ifstream target_is(target.c_str());
 	LLSD current = analyzeMetricPerformanceLog(target_is);
 	target_is.close();
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 537ed7f9634..3d047bc2ecd 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -72,6 +72,7 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
 LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ;
 LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ;
+const std::string sTesterName("TextureTester");
 
 S32 LLViewerTexture::sImageCount = 0;
 S32 LLViewerTexture::sRawCount = 0;
@@ -341,7 +342,7 @@ void LLViewerTextureManager::init()
 
 	LLViewerTexture::initClass() ;
 
-	if(LLFastTimer::sMetricLog)
+	if (LLFastTimer::sMetricLog && !LLViewerTextureManager::sTesterp && ((LLFastTimer::sLogName == sTesterName) || (LLFastTimer::sLogName == "metric")))
 	{
 		LLViewerTextureManager::sTesterp = new LLTexturePipelineTester() ;
         if (!LLViewerTextureManager::sTesterp->isValid())
@@ -3583,8 +3584,7 @@ F32 LLViewerMediaTexture::getMaxVirtualSize()
 //----------------------------------------------------------------------------------------------
 //start of LLTexturePipelineTester
 //----------------------------------------------------------------------------------------------
-LLTexturePipelineTester::LLTexturePipelineTester() :
-	LLMetricPerformanceTesterWithSession("TextureTester") 
+LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWithSession(sTesterName) 
 {
 	addMetric("TotalBytesLoaded") ;
 	addMetric("TotalBytesLoadedFromCache") ;
-- 
GitLab