From 39e5d2ecf04deceda92d6a53413298ca1c3bc0c7 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 8 Sep 2010 23:03:56 -0700
Subject: VWR-22761 : Rearchitecture of llmetricperformancetester and simple
 (non complete) implementation in llimagej2c

---
 indra/llcommon/CMakeLists.txt                |   2 +
 indra/llcommon/llmetricperformancetester.cpp | 245 ++++++++++++++++++++++++++
 indra/llcommon/llmetricperformancetester.h   | 197 +++++++++++++++++++++
 indra/llimage/llimagej2c.cpp                 |  86 +++++++++
 indra/llimage/llimagej2c.h                   |  40 +++++
 indra/newview/CMakeLists.txt                 |   2 -
 indra/newview/llappviewer.cpp                |   7 +-
 indra/newview/llfasttimerview.cpp            |  30 +++-
 indra/newview/llfasttimerview.h              |   1 +
 indra/newview/llmetricperformancetester.cpp  | 252 ---------------------------
 indra/newview/llmetricperformancetester.h    | 153 ----------------
 indra/newview/llviewertexture.cpp            |  83 +++++----
 indra/newview/llviewertexture.h              |   6 +-
 13 files changed, 645 insertions(+), 459 deletions(-)
 create mode 100644 indra/llcommon/llmetricperformancetester.cpp
 create mode 100644 indra/llcommon/llmetricperformancetester.h
 delete mode 100644 indra/newview/llmetricperformancetester.cpp
 delete mode 100644 indra/newview/llmetricperformancetester.h

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 2a036df06e..000648206f 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -54,6 +54,7 @@ set(llcommon_SOURCE_FILES
     llevents.cpp
     lleventtimer.cpp
     llfasttimer_class.cpp
+    llmetricperformancetester.cpp
     llfile.cpp
     llfindlocale.cpp
     llfixedbuffer.cpp
@@ -157,6 +158,7 @@ set(llcommon_HEADER_FILES
     lleventemitter.h
     llextendedstatus.h
     llfasttimer.h
+    llmetricperformancetester.h
     llfile.h
     llfindlocale.h
     llfixedbuffer.h
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
new file mode 100644
index 0000000000..bd548f199a
--- /dev/null
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -0,0 +1,245 @@
+/** 
+ * @file llmetricperformancetester.cpp
+ * @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "indra_constants.h"
+#include "llerror.h"
+#include "llsdserialize.h"
+#include "llstat.h"
+#include "lltreeiterators.h"
+#include "llmetricperformancetester.h"
+
+//----------------------------------------------------------------------------------------------
+// LLMetricPerformanceTesterBasic : static methods and testers management
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ;
+
+/*static*/ 
+void LLMetricPerformanceTesterBasic::cleanClass() 
+{
+	for (name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
+	{
+		delete iter->second ;
+	}
+	sTesterMap.clear() ;
+}
+
+/*static*/ 
+BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester) 
+{
+    llassert_always(tester != NULL);	
+	std::string name = tester->getTesterName() ;
+	if (getTester(name))
+	{
+		llerrs << "Tester name is already used by some other tester : " << name << llendl ;
+		return FALSE;
+	}
+
+	sTesterMap.insert(std::make_pair(name, tester));
+	return TRUE;
+}
+	
+/*static*/ 
+LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name) 
+{
+	name_tester_map_t::iterator found_it = sTesterMap.find(name) ;
+	if (found_it != sTesterMap.end())
+	{
+		return found_it->second ;
+	}
+	return NULL ;
+}
+	
+//----------------------------------------------------------------------------------------------
+// LLMetricPerformanceTesterBasic : Tester instance methods
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name) : 
+    mName(name),
+	mCount(0)
+{
+	if (mName == std::string())
+	{
+		llerrs << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << llendl ;
+	}
+
+	mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
+}
+
+LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic() 
+{
+}
+
+void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd) 
+{
+	incrementCurrentCount() ;
+	(*sd)[getCurrentLabelName()]["Name"] = mName ;
+}
+
+void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
+{
+	LLMutexLock lock(LLFastTimer::sLogLock);
+	LLFastTimer::sLogQueue.push((*sd));
+}
+
+void LLMetricPerformanceTesterBasic::outputTestResults() 
+{
+	LLSD sd;
+    
+	preOutputTestResults(&sd) ; 
+	outputTestRecord(&sd) ;
+	postOutputTestResults(&sd) ;
+}
+
+void LLMetricPerformanceTesterBasic::addMetric(std::string str)
+{
+	mMetricStrings.push_back(str) ;
+}
+
+/*virtual*/ 
+void LLMetricPerformanceTesterBasic::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) 
+{
+    resetCurrentCount() ;
+
+    std::string currentLabel = getCurrentLabelName();
+    BOOL in_base = (*base).has(currentLabel) ;
+    BOOL in_current = (*current).has(currentLabel) ;
+
+    while(in_base || in_current)
+    {
+        LLSD::String label = currentLabel ;		
+        
+        if(in_base && in_current)
+        {				
+            *os << llformat("%s\n", label.c_str()) ;
+
+            for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
+            {
+                switch((*current)[label][ mMetricStrings[index] ].type())
+                {
+                case LLSD::TypeInteger:
+                    compareTestResults(os, mMetricStrings[index], 
+                        (S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
+                    break ;
+                case LLSD::TypeReal:
+                    compareTestResults(os, mMetricStrings[index], 
+                        (F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
+                    break;
+                default:
+                    llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
+                }
+            }	
+        }
+
+        incrementCurrentCount();
+        currentLabel = getCurrentLabelName();
+        in_base = (*base).has(currentLabel) ;
+        in_current = (*current).has(currentLabel) ;
+    }
+}
+
+/*virtual*/ 
+void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) 
+{
+	*os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current, 
+						v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
+}
+
+/*virtual*/ 
+void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) 
+{
+	*os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,						
+						v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
+}
+
+//----------------------------------------------------------------------------------------------
+// LLMetricPerformanceTesterWithSession
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterWithSession::LLMetricPerformanceTesterWithSession(std::string name) : 
+    LLMetricPerformanceTesterBasic(name),
+    mBaseSessionp(NULL),
+    mCurrentSessionp(NULL)
+{
+}
+    
+LLMetricPerformanceTesterWithSession::~LLMetricPerformanceTesterWithSession()
+{
+	if (mBaseSessionp)
+	{
+		delete mBaseSessionp ;
+		mBaseSessionp = NULL ;
+	}
+	if (mCurrentSessionp)
+	{
+		delete mCurrentSessionp ;
+		mCurrentSessionp = NULL ;
+	}
+}
+
+/*virtual*/ 
+void LLMetricPerformanceTesterWithSession::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) 
+{
+    // Load the base session
+    resetCurrentCount() ;
+    mBaseSessionp = loadTestSession(base) ;
+    
+    // Load the current session
+    resetCurrentCount() ;
+    mCurrentSessionp = loadTestSession(current) ;
+    
+    if (!mBaseSessionp || !mCurrentSessionp)
+    {
+        llerrs << "Error loading test sessions." << llendl ;
+    }
+    
+    // Compare
+    compareTestSessions(os) ;
+    
+    // Release memory
+    if (mBaseSessionp)
+    {
+        delete mBaseSessionp ;
+        mBaseSessionp = NULL ;
+    }
+    if (mCurrentSessionp)
+    {
+        delete mCurrentSessionp ;
+        mCurrentSessionp = NULL ;
+    }
+}
+
+
+//----------------------------------------------------------------------------------------------
+// LLTestSession
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterWithSession::LLTestSession::~LLTestSession() 
+{
+}
+
diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h
new file mode 100644
index 0000000000..82d579b188
--- /dev/null
+++ b/indra/llcommon/llmetricperformancetester.h
@@ -0,0 +1,197 @@
+/** 
+ * @file llmetricperformancetester.h 
+ * @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes definition
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_METRICPERFORMANCETESTER_H 
+#define LL_METRICPERFORMANCETESTER_H 
+
+/**
+ * @class LLMetricPerformanceTesterBasic
+ * @brief Performance Metric Base Class
+ */
+class LL_COMMON_API LLMetricPerformanceTesterBasic
+{
+public:
+	/**
+     * @brief Creates a basic tester instance.
+     * @param[in] name - Unique string identifying this tester instance.
+     */
+	LLMetricPerformanceTesterBasic(std::string name);
+	virtual ~LLMetricPerformanceTesterBasic();
+
+	/**
+     * @return Returns true if the instance has been added to the tester map.
+     * Need to be tested after creation of a tester instance so to know if the tester is correctly handled.
+     * A tester might not be added to the map if another tester with the same name already exists.
+     */
+    BOOL isValid() const { return mValidInstance; }
+
+	/**
+     * @brief Write a set of test results to the log LLSD.
+     */
+	void outputTestResults() ;
+    
+	/**
+     * @brief Compare the test results.
+     * By default, compares the test results against the baseline one by one, item by item, 
+     * in the increasing order of the LLSD record counter, starting from the first one.
+     */
+	virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
+    
+	/**
+     * @return Returns the number of the test metrics in this tester instance.
+     */
+	S32 getNumberOfMetrics() const { return mMetricStrings.size() ;}
+	/**
+     * @return Returns the metric name at index
+     * @param[in] index - Index on the list of metrics managed by this tester instance.
+     */
+	std::string getMetricName(S32 index) const { return mMetricStrings[index] ;}
+    
+protected:
+	/**
+     * @return Returns the name of this tester instance.
+     */
+	std::string getTesterName() const { return mName ;}
+    
+	/**
+     * @brief Insert a new metric to be managed by this tester instance.
+     * @param[in] str - Unique string identifying the new metric.
+     */
+	void addMetric(std::string str) ;
+
+	/**
+     * @brief Compare test results, provided in 2 flavors: compare integers and compare floats.
+     * @param[out] os - Formatted output string holding the compared values.
+     * @param[in] metric_string - Name of the metric.
+     * @param[in] v_base - Base value of the metric.
+     * @param[in] v_current - Current value of the metric.
+     */
+	virtual void compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
+	virtual void compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
+    
+	/**
+     * @brief Reset internal record count. Count starts with 1.
+     */
+	void resetCurrentCount() { mCount = 1; }
+	/**
+     * @brief Increment internal record count.
+     */
+	void incrementCurrentCount() { mCount++; }
+	/**
+     * @return Returns the label to be used for the current count. It's "TesterName"-"Count".
+     */
+    std::string getCurrentLabelName() const { return llformat("%s-%d", mName.c_str(), mCount) ;}
+    
+    /**
+     * @brief Write a test record to the LLSD. Implementers need to overload this method.
+     * @param[out] sd - The LLSD record to store metric data into.
+     */
+	virtual void outputTestRecord(LLSD* sd) = 0 ;
+
+private:
+	void preOutputTestResults(LLSD* sd) ;
+	void postOutputTestResults(LLSD* sd) ;
+
+	std::string mName ;                         // Name of this tester instance
+	S32 mCount ;                                // Current record count
+    BOOL mValidInstance;                        // TRUE if the instance is managed by the map
+	std::vector< std::string > mMetricStrings ; // Metrics strings
+
+// Static members managing the collection of testers
+public:	
+    // Map of all the tester instances in use
+	typedef std::map< std::string, LLMetricPerformanceTesterBasic* > name_tester_map_t;	
+	static name_tester_map_t sTesterMap ;
+
+	/**
+     * @return Returns a pointer to the tester
+     * @param[in] name - Name of the tester instance queried.
+     */
+	static LLMetricPerformanceTesterBasic* getTester(std::string name) ;
+	/**
+     * @return Returns TRUE if there's a tester defined, FALSE otherwise.
+     */
+	static BOOL hasMetricPerformanceTesters() { return !sTesterMap.empty() ;}
+	/**
+     * @brief Delete all testers and reset the tester map
+     */
+	static void cleanClass() ;
+
+private:
+    // Add a tester to the map. Returns false if adding fails.
+	static BOOL addTester(LLMetricPerformanceTesterBasic* tester) ;    
+};
+
+/**
+ * @class LLMetricPerformanceTesterWithSession
+ * @brief Performance Metric Class with custom session 
+ */
+class LL_COMMON_API LLMetricPerformanceTesterWithSession : public LLMetricPerformanceTesterBasic
+{
+public:
+	/**
+     * @param[in] name - Unique string identifying this tester instance.
+     */
+	LLMetricPerformanceTesterWithSession(std::string name);
+	virtual ~LLMetricPerformanceTesterWithSession();
+
+	/**
+     * @brief Compare the test results.
+     * This will be loading the base and current sessions and compare them using the virtual 
+     * abstract methods loadTestSession() and compareTestSessions()
+     */
+	virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
+
+protected:
+    /**
+     * @class LLMetricPerformanceTesterWithSession::LLTestSession
+     * @brief Defines an interface for the two abstract virtual functions loadTestSession() and compareTestSessions()
+     */
+	class LLTestSession
+        {
+        public:
+            virtual ~LLTestSession() ;
+        };
+    
+	/**
+     * @brief Convert an LLSD log into a test session.
+     * @param[in] log - The LLSD record
+     * @return Returns the record as a test session
+     */
+	virtual LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) = 0;
+    
+	/**
+     * @brief Compare the base session and the target session. Assumes base and current sessions have been loaded.
+     * @param[out] os - The comparison result as a standard stream
+     */
+	virtual void compareTestSessions(std::ofstream* os) = 0;
+    
+	LLTestSession* mBaseSessionp;
+	LLTestSession* mCurrentSessionp;
+};
+
+#endif
+
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index c8c866b7f2..72aa253568 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -30,6 +30,7 @@
 #include "lldir.h"
 #include "llimagej2c.h"
 #include "llmemtype.h"
+#include "lltimer.h"
 
 typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
 typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
@@ -51,6 +52,9 @@ LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
 void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
 const char* fallbackEngineInfoLLImageJ2CImpl();
 
+// Test data gathering handle
+LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ;
+
 //static
 //Loads the required "create", "destroy" and "engineinfo" functions needed
 void LLImageJ2C::openDSO()
@@ -195,6 +199,16 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 	{	// Array size is MAX_DISCARD_LEVEL+1
 		mDataSizes[i] = 0;
 	}
+
+	if (LLFastTimer::sMetricLog && !LLImageJ2C::sTesterp)
+	{
+		LLImageJ2C::sTesterp = new LLImageCompressionTester() ;
+        if (!LLImageJ2C::sTesterp->isValid())
+        {
+            delete LLImageJ2C::sTesterp;
+            LLImageJ2C::sTesterp = NULL;
+        }
+	}
 }
 
 // virtual
@@ -297,7 +311,12 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
 		// Update the raw discard level
 		updateRawDiscardLevel();
 		mDecoding = TRUE;
+        LLTimer elapsed;
 		res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
+        if (LLImageJ2C::sTesterp)
+        {
+            LLImageJ2C::sTesterp->updateDecompressionStats(this->getDataSize(), raw_imagep->getDataSize(), elapsed.getElapsedTimeF32()) ;
+        }
 	}
 	
 	if (res)
@@ -540,3 +559,70 @@ void LLImageJ2C::updateRawDiscardLevel()
 LLImageJ2CImpl::~LLImageJ2CImpl()
 {
 }
+
+//----------------------------------------------------------------------------------------------
+// Start of LLImageCompressionTester
+//----------------------------------------------------------------------------------------------
+LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTesterBasic("ImageCompressionTester") 
+{
+	addMetric("TotalBytesInDecompression");
+	addMetric("TotalBytesOutDecompression");
+	addMetric("TotalBytesInCompression");
+	addMetric("TotalBytesOutCompression");
+    
+	addMetric("TimeTimeDecompression");
+	addMetric("TimeTimeCompression");
+	
+    mTotalBytesInDecompression = 0;
+    mTotalBytesOutDecompression = 0;
+    mTotalBytesInCompression = 0;
+    mTotalBytesOutCompression = 0;
+
+
+    mTotalTimeDecompression = 0.0f;
+    mTotalTimeCompression = 0.0f;
+}
+
+LLImageCompressionTester::~LLImageCompressionTester()
+{
+	LLImageJ2C::sTesterp = NULL;
+}
+
+//virtual 
+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;
+}
+
+void LLImageCompressionTester::updateCompressionStats(const S32 bytesIn, const S32 bytesOut, const F32 deltaTime) 
+{
+    mTotalBytesInCompression += bytesIn;
+    mTotalBytesOutCompression += bytesOut;
+    mTotalTimeCompression += deltaTime;
+}
+
+void LLImageCompressionTester::updateDecompressionStats(const S32 bytesIn, const S32 bytesOut, const F32 deltaTime) 
+{
+    mTotalBytesInDecompression += bytesIn;
+    mTotalBytesOutDecompression += bytesOut;
+    mTotalTimeDecompression += deltaTime;
+    if (mTotalBytesInDecompression > (5*1000000))
+    {
+        outputTestResults();
+        mTotalBytesInDecompression = 0;
+        mTotalBytesOutDecompression = 0;
+        mTotalTimeDecompression = 0.0f;
+    }
+}
+
+//----------------------------------------------------------------------------------------------
+// End of LLTexturePipelineTester
+//----------------------------------------------------------------------------------------------
+
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index cdb3faa207..eeb00de6d2 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -29,8 +29,11 @@
 
 #include "llimage.h"
 #include "llassettype.h"
+#include "llmetricperformancetester.h"
 
 class LLImageJ2CImpl;
+class LLImageCompressionTester ;
+
 class LLImageJ2C : public LLImageFormatted
 {
 protected:
@@ -72,6 +75,9 @@ public:
 	static void openDSO();
 	static void closeDSO();
 	static std::string getEngineInfo();
+
+    // Image compression/decompression tester
+	static LLImageCompressionTester* sTesterp ;
 	
 protected:
 	friend class LLImageJ2CImpl;
@@ -118,4 +124,38 @@ protected:
 
 #define LINDEN_J2C_COMMENT_PREFIX "LL_"
 
+//
+// This class is used for performance data gathering only.
+// Tracks the image compression / decompression data,
+// records and outputs them to metric log files.
+//
+
+class LLImageCompressionTester : public LLMetricPerformanceTesterBasic
+{
+    public:
+        LLImageCompressionTester();
+        ~LLImageCompressionTester();
+        
+        void updateDecompressionStats(const S32 bytesIn, const S32 bytesOut, const F32 deltaTime) ;
+        void updateCompressionStats(const S32 bytesIn, const S32 bytesOut, const F32 deltaTime) ;
+        
+    protected:
+        /*virtual*/ void outputTestRecord(LLSD* sd);
+        
+    private:
+        //
+        // Data size
+        //
+        U32 mTotalBytesInDecompression;     // Total bytes fed to decompressor
+        U32 mTotalBytesOutDecompression;    // Total bytes produced by decompressor
+        U32 mTotalBytesInCompression;       // Total bytes fed to compressor
+        U32 mTotalBytesOutCompression;      // Total bytes produced by compressor
+        
+        //
+        // Time
+        //
+        F32 mTotalTimeDecompression;        // Total time spent in computing decompression
+        F32 mTotalTimeCompression;          // Total time spent in computing compression
+    };
+
 #endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 630902c48f..546f8268d0 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -284,7 +284,6 @@ set(viewer_SOURCE_FILES
     llmediadataclient.cpp
     llmemoryview.cpp
     llmenucommands.cpp
-    llmetricperformancetester.cpp
     llmimetypes.cpp
     llmorphview.cpp
     llmoveview.cpp
@@ -808,7 +807,6 @@ set(viewer_HEADER_FILES
     llmediadataclient.h
     llmemoryview.h
     llmenucommands.h
-    llmetricperformancetester.h
     llmimetypes.h
     llmorphview.h
     llmoveview.h
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index bfe3e52657..d383c9adbc 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -536,6 +536,7 @@ public:
 
 		os.close();
 	}
+
 };
 
 //virtual
@@ -1279,7 +1280,7 @@ bool LLAppViewer::cleanup()
 {
 	// workaround for DEV-35406 crash on shutdown
 	LLEventPumps::instance().reset();
-
+    
 	// remove any old breakpad minidump files from the log directory
 	if (! isError())
 	{
@@ -1630,7 +1631,7 @@ bool LLAppViewer::cleanup()
 				gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_report.csv"));
 		}
 	}
-	LLMetricPerformanceTester::cleanClass() ;
+	LLMetricPerformanceTesterBasic::cleanClass() ;
 
 	llinfos << "Cleaning up Media and Textures" << llendflush;
 
@@ -2124,7 +2125,7 @@ bool LLAppViewer::initConfiguration()
 	{
 		LLFastTimerView::sAnalyzePerformance = TRUE;
 	}
-
+    
 	if (clp.hasOption("replaysession"))
 	{
 		LLAgentPilot::sReplaySession = TRUE;
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index b715647143..07ff3a91a1 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -1144,15 +1144,15 @@ LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
 		{
 			std::string label = iter->first;
 
-			LLMetricPerformanceTester* tester = LLMetricPerformanceTester::getTester(iter->second["Name"].asString()) ;
+			LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
 			if(tester)
 			{
 				ret[label]["Name"] = iter->second["Name"] ;
 
-				S32 num_of_strings = tester->getNumOfMetricStrings() ;
-				for(S32 index = 0 ; index < num_of_strings ; index++)
+				S32 num_of_metrics = tester->getNumberOfMetrics() ;
+				for(S32 index = 0 ; index < num_of_metrics ; index++)
 				{
-					ret[label][ tester->getMetricString(index) ] = iter->second[ tester->getMetricString(index) ] ;
+					ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
 				}
 			}
 		}
@@ -1161,10 +1161,24 @@ LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
 	return ret;
 }
 
+//static
+void LLFastTimerView::outputAllMetrics()
+{
+	if (LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
+	{
+        for (LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin(); 
+            iter != LLMetricPerformanceTesterBasic::sTesterMap.end(); ++iter)
+        {
+            LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second);	
+            tester->outputTestResults();
+        }
+	}
+}
+
 //static
 void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
 {
-	if(!LLMetricPerformanceTester::hasMetricPerformanceTesters())
+	if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
 	{
 		return ;
 	}
@@ -1183,10 +1197,10 @@ void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target
 	std::ofstream os(output.c_str());
 	
 	os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n"; 
-	for(LLMetricPerformanceTester::name_tester_map_t::iterator iter = LLMetricPerformanceTester::sTesterMap.begin() ; 
-		iter != LLMetricPerformanceTester::sTesterMap.end() ; ++iter)
+	for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ; 
+		iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter)
 	{
-		LLMetricPerformanceTester* tester = ((LLMetricPerformanceTester*)iter->second) ;	
+		LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ;	
 		tester->analyzePerformance(&os, &base, &current) ;
 	}
 	
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index 961d03abf1..54025267ee 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -37,6 +37,7 @@ public:
 	
 	static BOOL sAnalyzePerformance;
 
+    static void outputAllMetrics();
 	static void doAnalysis(std::string baseline, std::string target, std::string output);
 
 private:
diff --git a/indra/newview/llmetricperformancetester.cpp b/indra/newview/llmetricperformancetester.cpp
deleted file mode 100644
index 903c97378e..0000000000
--- a/indra/newview/llmetricperformancetester.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/** 
- * @file llmetricperformancetester.cpp
- * @brief LLMetricPerformanceTester class implementation
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "indra_constants.h"
-#include "llerror.h"
-#include "llmath.h"
-#include "llfontgl.h"
-#include "llsdserialize.h"
-#include "llstat.h"
-#include "lltreeiterators.h"
-#include "llmetricperformancetester.h"
-
-LLMetricPerformanceTester::name_tester_map_t LLMetricPerformanceTester::sTesterMap ;
-
-//static 
-void LLMetricPerformanceTester::initClass() 
-{
-}
-//static 
-void LLMetricPerformanceTester::cleanClass() 
-{
-	for(name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
-	{
-		delete iter->second ;
-	}
-	sTesterMap.clear() ;
-}
-
-//static 
-void LLMetricPerformanceTester::addTester(LLMetricPerformanceTester* tester) 
-{
-	if(!tester)
-	{
-		llerrs << "invalid tester!" << llendl ;
-		return ;
-	}
-	
-	std::string name = tester->getName() ;
-	if(getTester(name))
-	{
-		llerrs << "Tester name is used by some other tester: " << name << llendl ;
-		return ;
-	}
-
-	sTesterMap.insert(std::make_pair(name, tester));
-
-	return ;
-}
-	
-//static 
-LLMetricPerformanceTester* LLMetricPerformanceTester::getTester(std::string label) 
-{
-	name_tester_map_t::iterator found_it = sTesterMap.find(label) ;
-	if(found_it != sTesterMap.end())
-	{
-		return found_it->second ;
-	}
-
-	return NULL ;
-}
-	
-LLMetricPerformanceTester::LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis)
-	: mName(name),
-	mBaseSessionp(NULL),
-	mCurrentSessionp(NULL),
-	mCount(0),
-	mUseDefaultPerformanceAnalysis(use_default_performance_analysis)
-{
-	if(mName == std::string())
-	{
-		llerrs << "invalid name." << llendl ;
-	}
-
-	LLMetricPerformanceTester::addTester(this) ;
-}
-
-/*virtual*/ 
-LLMetricPerformanceTester::~LLMetricPerformanceTester() 
-{
-	if(mBaseSessionp)
-	{
-		delete mBaseSessionp ;
-		mBaseSessionp = NULL ;
-	}
-	if(mCurrentSessionp)
-	{
-		delete mCurrentSessionp ;
-		mCurrentSessionp = NULL ;
-	}
-}
-
-void LLMetricPerformanceTester::incLabel()
-{
-	mCurLabel = llformat("%s-%d", mName.c_str(), mCount++) ;
-}
-void LLMetricPerformanceTester::preOutputTestResults(LLSD* sd) 
-{
-	incLabel() ;
-	(*sd)[mCurLabel]["Name"] = mName ;
-}
-void LLMetricPerformanceTester::postOutputTestResults(LLSD* sd)
-{
-	LLMutexLock lock(LLFastTimer::sLogLock);
-	LLFastTimer::sLogQueue.push((*sd));
-}
-
-void LLMetricPerformanceTester::outputTestResults() 
-{
-	LLSD sd ;
-	preOutputTestResults(&sd) ; 
-
-	outputTestRecord(&sd) ;
-
-	postOutputTestResults(&sd) ;
-}
-
-void LLMetricPerformanceTester::addMetricString(std::string str)
-{
-	mMetricStrings.push_back(str) ;
-}
-
-const std::string& LLMetricPerformanceTester::getMetricString(U32 index) const 
-{
-	return mMetricStrings[index] ;
-}
-
-void LLMetricPerformanceTester::prePerformanceAnalysis() 
-{
-	mCount = 0 ;
-	incLabel() ;
-}
-
-//
-//default analyzing the performance
-//
-/*virtual*/ 
-void LLMetricPerformanceTester::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) 
-{
-	if(mUseDefaultPerformanceAnalysis)//use default performance analysis
-	{
-		prePerformanceAnalysis() ;
-
-		BOOL in_base = (*base).has(mCurLabel) ;
-		BOOL in_current = (*current).has(mCurLabel) ;
-
-		while(in_base || in_current)
-		{
-			LLSD::String label = mCurLabel ;		
-			
-			if(in_base && in_current)
-			{				
-				*os << llformat("%s\n", label.c_str()) ;
-
-				for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
-				{
-					switch((*current)[label][ mMetricStrings[index] ].type())
-					{
-					case LLSD::TypeInteger:
-						compareTestResults(os, mMetricStrings[index], 
-							(S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
-						break ;
-					case LLSD::TypeReal:
-						compareTestResults(os, mMetricStrings[index], 
-							(F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
-						break;
-					default:
-						llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
-					}
-				}	
-			}
-
-			incLabel() ;
-			in_base = (*base).has(mCurLabel) ;
-			in_current = (*current).has(mCurLabel) ;
-		}
-	}//end of default
-	else
-	{
-		//load the base session
-		prePerformanceAnalysis() ;
-		mBaseSessionp = loadTestSession(base) ;
-
-		//load the current session
-		prePerformanceAnalysis() ;
-		mCurrentSessionp = loadTestSession(current) ;
-
-		if(!mBaseSessionp || !mCurrentSessionp)
-		{
-			llerrs << "memory error during loading test sessions." << llendl ;
-		}
-
-		//compare
-		compareTestSessions(os) ;
-
-		//release memory
-		if(mBaseSessionp)
-		{
-			delete mBaseSessionp ;
-			mBaseSessionp = NULL ;
-		}
-		if(mCurrentSessionp)
-		{
-			delete mCurrentSessionp ;
-			mCurrentSessionp = NULL ;
-		}
-	}
-}
-
-//virtual 
-void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) 
-{
-	*os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current, 
-						v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
-}
-
-//virtual 
-void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) 
-{
-	*os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,						
-						v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
-}
-
-//virtual 
-LLMetricPerformanceTester::LLTestSession::~LLTestSession() 
-{
-}
-
diff --git a/indra/newview/llmetricperformancetester.h b/indra/newview/llmetricperformancetester.h
deleted file mode 100644
index 6f5dc03564..0000000000
--- a/indra/newview/llmetricperformancetester.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/** 
- * @file LLMetricPerformanceTester.h 
- * @brief LLMetricPerformanceTester class definition
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METRICPERFORMANCETESTER_H 
-#define LL_METRICPERFORMANCETESTER_H 
-
-class LLMetricPerformanceTester 
-{
-public:
-	//
-    //name passed to the constructor is a unique string for each tester.
-    //an error is reported if the name is already used by some other tester.
-    //
-	LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis) ;
-	virtual ~LLMetricPerformanceTester();
-
-	//
-    //return the name of the tester
-    //
-	std::string getName() const { return mName ;}
-	//
-    //return the number of the test metrics in this tester
-    //
-	S32 getNumOfMetricStrings() const { return mMetricStrings.size() ;}
-	//
-    //return the metric string at the index
-    //
-	const std::string& getMetricString(U32 index) const ;
-
-	//
-    //this function to compare the test results.
-    //by default, it compares the test results against the baseline one by one, item by item, 
-    //in the increasing order of the LLSD label counter, starting from the first one.
-	//you can define your own way to analyze performance by passing FALSE to "use_default_performance_analysis",
-    //and implement two abstract virtual functions below: loadTestSession(...) and compareTestSessions(...).
-    //
-	void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
-
-protected:
-	//
-    //insert metric strings used in the tester.
-    //
-	void addMetricString(std::string str) ;
-
-	//
-    //increase LLSD label by 1
-    //
-	void incLabel() ;
-	
-	//
-    //the function to write a set of test results to the log LLSD.
-    //
-	void outputTestResults() ;
-
-	//
-    //compare the test results.
-    //you can write your own to overwrite the default one.
-    //
-	virtual void compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
-	virtual void compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
-
-	//
-	//for performance analysis use 
-	//it defines an interface for the two abstract virtual functions loadTestSession(...) and compareTestSessions(...).
-    //please make your own test session class derived from it.
-	//
-	class LLTestSession
-	{
-	public:
-		virtual ~LLTestSession() ;
-	};
-
-	//
-    //load a test session for log LLSD
-    //you need to implement it only when you define your own way to analyze performance.
-    //otherwise leave it empty.
-    //
-	virtual LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) = 0 ;
-	//
-    //compare the base session and the target session
-    //you need to implement it only when you define your own way to analyze performance.
-    //otherwise leave it empty.
-    //
-	virtual void compareTestSessions(std::ofstream* os) = 0 ;
-	//
-    //the function to write a set of test results to the log LLSD.
-    //you have to write you own version of this function.	
-	//
-	virtual void outputTestRecord(LLSD* sd) = 0 ;
-
-private:
-	void preOutputTestResults(LLSD* sd) ;
-	void postOutputTestResults(LLSD* sd) ;
-	void prePerformanceAnalysis() ;
-
-protected:
-	//
-    //the unique name string of the tester
-    //
-	std::string mName ;
-	//
-    //the current label counter for the log LLSD
-    //
-	std::string mCurLabel ;
-	S32 mCount ;
-	
-	BOOL mUseDefaultPerformanceAnalysis ;
-	LLTestSession* mBaseSessionp ;
-	LLTestSession* mCurrentSessionp ;
-
-	//metrics strings
-	std::vector< std::string > mMetricStrings ;
-
-//static members
-private:
-	static void addTester(LLMetricPerformanceTester* tester) ;
-
-public:	
-	typedef std::map< std::string, LLMetricPerformanceTester* > name_tester_map_t;	
-	static name_tester_map_t sTesterMap ;
-
-	static LLMetricPerformanceTester* getTester(std::string label) ;
-	static BOOL hasMetricPerformanceTesters() {return !sTesterMap.empty() ;}
-
-	static void initClass() ;
-	static void cleanClass() ;
-};
-
-#endif
-
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 0ad54f238e..99a9469ddb 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -344,6 +344,11 @@ void LLViewerTextureManager::init()
 	if(LLFastTimer::sMetricLog)
 	{
 		LLViewerTextureManager::sTesterp = new LLTexturePipelineTester() ;
+        if (!LLViewerTextureManager::sTesterp->isValid())
+        {
+            delete LLViewerTextureManager::sTesterp;
+            LLViewerTextureManager::sTesterp = NULL;
+        }
 	}
 }
 
@@ -3579,22 +3584,22 @@ F32 LLViewerMediaTexture::getMaxVirtualSize()
 //start of LLTexturePipelineTester
 //----------------------------------------------------------------------------------------------
 LLTexturePipelineTester::LLTexturePipelineTester() :
-	LLMetricPerformanceTester("TextureTester", FALSE) 
-{
-	addMetricString("TotalBytesLoaded") ;
-	addMetricString("TotalBytesLoadedFromCache") ;
-	addMetricString("TotalBytesLoadedForLargeImage") ;
-	addMetricString("TotalBytesLoadedForSculpties") ;
-	addMetricString("StartFetchingTime") ;
-	addMetricString("TotalGrayTime") ;
-	addMetricString("TotalStablizingTime") ;
-	addMetricString("StartTimeLoadingSculpties") ;
-	addMetricString("EndTimeLoadingSculpties") ;
-
-	addMetricString("Time") ;
-	addMetricString("TotalBytesBound") ;
-	addMetricString("TotalBytesBoundForLargeImage") ;
-	addMetricString("PercentageBytesBound") ;
+	LLMetricPerformanceTesterWithSession("TextureTester") 
+{
+	addMetric("TotalBytesLoaded") ;
+	addMetric("TotalBytesLoadedFromCache") ;
+	addMetric("TotalBytesLoadedForLargeImage") ;
+	addMetric("TotalBytesLoadedForSculpties") ;
+	addMetric("StartFetchingTime") ;
+	addMetric("TotalGrayTime") ;
+	addMetric("TotalStablizingTime") ;
+	addMetric("StartTimeLoadingSculpties") ;
+	addMetric("EndTimeLoadingSculpties") ;
+
+	addMetric("Time") ;
+	addMetric("TotalBytesBound") ;
+	addMetric("TotalBytesBoundForLargeImage") ;
+	addMetric("PercentageBytesBound") ;
 	
 	mTotalBytesLoaded = 0 ;
 	mTotalBytesLoadedFromCache = 0 ;	
@@ -3672,22 +3677,23 @@ void LLTexturePipelineTester::reset()
 //virtual 
 void LLTexturePipelineTester::outputTestRecord(LLSD *sd) 
 {	
-	(*sd)[mCurLabel]["TotalBytesLoaded"]              = (LLSD::Integer)mTotalBytesLoaded ;
-	(*sd)[mCurLabel]["TotalBytesLoadedFromCache"]     = (LLSD::Integer)mTotalBytesLoadedFromCache ;
-	(*sd)[mCurLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
-	(*sd)[mCurLabel]["TotalBytesLoadedForSculpties"]  = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
+    std::string currentLabel = getCurrentLabelName();
+	(*sd)[currentLabel]["TotalBytesLoaded"]              = (LLSD::Integer)mTotalBytesLoaded ;
+	(*sd)[currentLabel]["TotalBytesLoadedFromCache"]     = (LLSD::Integer)mTotalBytesLoadedFromCache ;
+	(*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
+	(*sd)[currentLabel]["TotalBytesLoadedForSculpties"]  = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
 
-	(*sd)[mCurLabel]["StartFetchingTime"]             = (LLSD::Real)mStartFetchingTime ;
-	(*sd)[mCurLabel]["TotalGrayTime"]                 = (LLSD::Real)mTotalGrayTime ;
-	(*sd)[mCurLabel]["TotalStablizingTime"]           = (LLSD::Real)mTotalStablizingTime ;
+	(*sd)[currentLabel]["StartFetchingTime"]             = (LLSD::Real)mStartFetchingTime ;
+	(*sd)[currentLabel]["TotalGrayTime"]                 = (LLSD::Real)mTotalGrayTime ;
+	(*sd)[currentLabel]["TotalStablizingTime"]           = (LLSD::Real)mTotalStablizingTime ;
 
-	(*sd)[mCurLabel]["StartTimeLoadingSculpties"]     = (LLSD::Real)mStartTimeLoadingSculpties ;
-	(*sd)[mCurLabel]["EndTimeLoadingSculpties"]       = (LLSD::Real)mEndTimeLoadingSculpties ;
+	(*sd)[currentLabel]["StartTimeLoadingSculpties"]     = (LLSD::Real)mStartTimeLoadingSculpties ;
+	(*sd)[currentLabel]["EndTimeLoadingSculpties"]       = (LLSD::Real)mEndTimeLoadingSculpties ;
 
-	(*sd)[mCurLabel]["Time"]                          = LLImageGL::sLastFrameTime ;
-	(*sd)[mCurLabel]["TotalBytesBound"]               = (LLSD::Integer)mLastTotalBytesUsed ;
-	(*sd)[mCurLabel]["TotalBytesBoundForLargeImage"]  = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
-	(*sd)[mCurLabel]["PercentageBytesBound"]          = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
+	(*sd)[currentLabel]["Time"]                          = LLImageGL::sLastFrameTime ;
+	(*sd)[currentLabel]["TotalBytesBound"]               = (LLSD::Integer)mLastTotalBytesUsed ;
+	(*sd)[currentLabel]["TotalBytesBoundForLargeImage"]  = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
+	(*sd)[currentLabel]["PercentageBytesBound"]          = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
 }
 
 void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep) 
@@ -3776,7 +3782,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os)
 	}
 
 	//compare and output the comparison
-	*os << llformat("%s\n", mName.c_str()) ;
+	*os << llformat("%s\n", getTesterName().c_str()) ;
 	*os << llformat("AggregateResults\n") ;
 
 	compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime) ;
@@ -3831,7 +3837,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os)
 }
 
 //virtual 
-LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
+LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
 {
 	LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession() ;
 	if(!sessionp)
@@ -3858,12 +3864,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi
 	sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
 	
 	//load a session
-	BOOL in_log = (*log).has(mCurLabel) ;
-	while(in_log)
+    std::string currentLabel = getCurrentLabelName();
+	BOOL in_log = (*log).has(currentLabel) ;
+	while (in_log)
 	{
-		LLSD::String label = mCurLabel ;		
-		incLabel() ;
-		in_log = (*log).has(mCurLabel) ;
+		LLSD::String label = currentLabel ;		
 
 		if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size())
 		{
@@ -3929,7 +3934,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi
 			sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ;
 			sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ;
 			sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
-		}		
+		}
+        // Next label
+		incrementCurrentCount() ;
+        currentLabel = getCurrentLabelName();
+		in_log = (*log).has(currentLabel) ;
 	}
 
 	sessionp->mTotalFetchingTime += total_fetching_time ;
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 7cb8bea4c8..6ea717c8b1 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -732,7 +732,7 @@ public:
 //it tracks the activities of the texture pipeline
 //records them, and outputs them to log files
 //
-class LLTexturePipelineTester : public LLMetricPerformanceTester
+class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession
 {
 	enum
 	{
@@ -748,8 +748,6 @@ public:
 	void updateGrayTextureBinding() ;
 	void setStablizingTime() ;
 
-	/*virtual*/ void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
-
 private:
 	void reset() ;
 	void updateStablizingTime() ;
@@ -820,7 +818,7 @@ private:
 		S32 mInstantPerformanceListCounter ;
 	};
 
-	/*virtual*/ LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) ;
+	/*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ;
 	/*virtual*/ void compareTestSessions(std::ofstream* os) ;
 };
 
-- 
cgit v1.2.3