VWR-22761 : Rearchitecture of llmetricperformancetester and simple (non complete) implementation in llimagej2c

master
Merov Linden 2010-09-08 23:03:56 -07:00
parent 63f2ddf377
commit 39e5d2ecf0
13 changed files with 643 additions and 457 deletions

View File

@ -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

View File

@ -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()
{
}

View File

@ -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

View File

@ -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
//----------------------------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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) ;
}

View File

@ -37,6 +37,7 @@ public:
static BOOL sAnalyzePerformance;
static void outputAllMetrics();
static void doAnalysis(std::string baseline, std::string target, std::string output);
private:

View File

@ -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()
{
}

View File

@ -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

View File

@ -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)
LLMetricPerformanceTesterWithSession("TextureTester")
{
addMetricString("TotalBytesLoaded") ;
addMetricString("TotalBytesLoadedFromCache") ;
addMetricString("TotalBytesLoadedForLargeImage") ;
addMetricString("TotalBytesLoadedForSculpties") ;
addMetricString("StartFetchingTime") ;
addMetricString("TotalGrayTime") ;
addMetricString("TotalStablizingTime") ;
addMetricString("StartTimeLoadingSculpties") ;
addMetricString("EndTimeLoadingSculpties") ;
addMetric("TotalBytesLoaded") ;
addMetric("TotalBytesLoadedFromCache") ;
addMetric("TotalBytesLoadedForLargeImage") ;
addMetric("TotalBytesLoadedForSculpties") ;
addMetric("StartFetchingTime") ;
addMetric("TotalGrayTime") ;
addMetric("TotalStablizingTime") ;
addMetric("StartTimeLoadingSculpties") ;
addMetric("EndTimeLoadingSculpties") ;
addMetricString("Time") ;
addMetricString("TotalBytesBound") ;
addMetricString("TotalBytesBoundForLargeImage") ;
addMetricString("PercentageBytesBound") ;
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 ;

View File

@ -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) ;
};