Merge pull request #205 from secondlife/sl-19676-360mode-stats

sl-19676 - Stats on updates and scene loading
meow-7.2.2
simon-linden 2023-05-09 09:27:53 -07:00 committed by GitHub
commit a9c64940cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 440 additions and 281 deletions

View File

@ -17085,5 +17085,38 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>StatsReportMaxDuration</key>
<map>
<key>Comment</key>
<string>Maximum seconds for viewer stats file data, prevents huge file</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>300</real>
</map>
<key>StatsReportFileInterval</key>
<map>
<key>Comment</key>
<string>Interval to save viewer stats file data</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.2</real>
</map>
<key>StatsReportSkipZeroDataSaves</key>
<map>
<key>Comment</key>
<string>In viewer stats data file, skip saving entry if there is no data</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
</llsd>

View File

@ -1536,7 +1536,12 @@ bool LLAppViewer::doFrame()
LLFloaterSimpleOutfitSnapshot::update();
gGLActive = FALSE;
}
}
if (LLViewerStatsRecorder::instanceExists())
{
LLViewerStatsRecorder::instance().idle();
}
}
}
{

View File

@ -197,21 +197,18 @@ void LLFloater360Capture::changeInterestListMode(bool send_everything)
if (gAgent.requestPostCapability("InterestList", body, [](const LLSD & response)
{
LL_INFOS("360Capture") <<
"InterestList capability responded: \n" <<
LL_DEBUGS("360Capture") << "InterestList capability responded: \n" <<
ll_pretty_print_sd(response) <<
LL_ENDL;
}))
{
LL_INFOS("360Capture") <<
"Successfully posted an InterestList capability request with payload: \n" <<
LL_DEBUGS("360Capture") << "Successfully posted an InterestList capability request with payload: \n" <<
ll_pretty_print_sd(body) <<
LL_ENDL;
}
else
{
LL_INFOS("360Capture") <<
"Unable to post an InterestList capability request with payload: \n" <<
LL_WARNS("360Capture") << "Unable to post an InterestList capability request with payload: \n" <<
ll_pretty_print_sd(body) <<
LL_ENDL;
}
@ -632,11 +629,8 @@ void LLFloater360Capture::capture360Images()
// display time to encode all 6 images. It tends to be a fairly linear
// time for each so we don't need to worry about displaying the time
// for each - this gives us plenty to use for optimizing
LL_INFOS("360Capture") <<
"Time to encode and save 6 images was " <<
encode_time_total <<
" seconds" <<
LL_ENDL;
LL_INFOS("360Capture") << "Time to encode and save 6 images was " <<
encode_time_total << " seconds" << LL_ENDL;
// Write the JavaScript file footer (the bottom of the file after the
// declarations of the actual data URLs array). The footer comprises of
@ -668,7 +662,7 @@ void LLFloater360Capture::capture360Images()
// as a change - only the subsequent 5 are
if (camera_changed_times < 5)
{
LL_INFOS("360Capture") << "Warning: we only captured " << camera_changed_times << " images." << LL_ENDL;
LL_WARNS("360Capture") << "360 image capture expected 5 or more images, only captured " << camera_changed_times << " images." << LL_ENDL;
}
// now we have the 6 shots saved in a well specified location,

View File

@ -56,6 +56,7 @@
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerstatsrecorder.h"
#include "llviewertexturelist.h"
#include "llvolume.h"
#include "llvolumemgr.h"
@ -4089,6 +4090,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
}
mLoadingMeshes[detail].erase(obj_iter);
LLViewerStatsRecorder::instance().meshLoaded();
}
}

View File

@ -2183,7 +2183,6 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response,
LL_DEBUGS(LOG_TXT) << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL;
if (data_size > 0)
{
LLViewerStatsRecorder::instance().textureFetch(data_size);
// *TODO: set the formatted image data here directly to avoid the copy
// Hold on to body for later copy
@ -2249,6 +2248,13 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response,
mHaveAllData = TRUE;
}
mRequestedSize = data_size;
if (mHaveAllData)
{
LLViewerStatsRecorder::instance().textureFetch();
}
// *TODO: set the formatted image data here directly to avoid the copy
}
else
{
@ -2258,11 +2264,6 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response,
mLoaded = TRUE;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
if (LLViewerStatsRecorder::instanceExists())
{
// Do not create this instance inside thread
LLViewerStatsRecorder::instance().log(0.2f);
}
return data_size ;
}

View File

@ -119,6 +119,7 @@
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
#include "llviewerstats.h"
#include "llviewerstatsrecorder.h"
#include "llvoavatarself.h"
#include "llvoicevivox.h"
#include "llworldmap.h"
@ -1295,49 +1296,99 @@ class LLAdvancedDumpRegionObjectCache : public view_listener_t
}
};
class LLAdvancedInterestListFullUpdate : public view_listener_t
class LLAdvancedToggleInterestList360Mode : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
LLSD request;
LLSD body;
static bool using_360 = false;
public:
bool handleEvent(const LLSD &userdata)
{
LLSD request;
LLSD body;
if (using_360)
{
body["mode"] = LLSD::String("default");
}
else
{
body["mode"] = LLSD::String("360");
}
using_360 = !using_360;
// First do a GET to report on current mode and update stats
if (gAgent.requestGetCapability("InterestList",
[](const LLSD &response) {
LL_DEBUGS("360Capture") << "InterestList capability GET responded: \n"
<< ll_pretty_print_sd(response) << LL_ENDL;
}))
{
LL_DEBUGS("360Capture") << "Successful GET InterestList capability request with return body: \n"
<< ll_pretty_print_sd(body) << LL_ENDL;
}
else
{
LL_WARNS("360Capture") << "Unable to GET InterestList capability request with return body: \n"
<< ll_pretty_print_sd(body) << LL_ENDL;
}
if (gAgent.requestPostCapability("InterestList", body, [](const LLSD& response)
// Now do a POST to change the mode
if (sUsing360)
{
LL_INFOS("360Capture") <<
"InterestList capability responded: \n" <<
ll_pretty_print_sd(response) <<
LL_ENDL;
}))
body["mode"] = LLSD::String("default");
}
else
{
LL_INFOS("360Capture") <<
"Successfully posted an InterestList capability request with payload: \n" <<
ll_pretty_print_sd(body) <<
LL_ENDL;
body["mode"] = LLSD::String("360");
}
sUsing360 = !sUsing360;
LL_INFOS("360Capture") << "Setting InterestList capability mode to " << body["mode"].asString() << LL_ENDL;
if (gAgent.requestPostCapability("InterestList", body,
[](const LLSD &response) {
LL_DEBUGS("360Capture") << "InterestList capability responded: \n"
<< ll_pretty_print_sd(response) << LL_ENDL;
}))
{
LL_DEBUGS("360Capture") << "Successfully posted an InterestList capability request with payload: \n"
<< ll_pretty_print_sd(body) << LL_ENDL;
return true;
}
else
{
LL_INFOS("360Capture") <<
"Unable to post an InterestList capability request with payload: \n" <<
ll_pretty_print_sd(body) <<
LL_ENDL;
LL_DEBUGS("360Capture") << "Unable to post an InterestList capability request with payload: \n"
<< ll_pretty_print_sd(body) << LL_ENDL;
return false;
}
};
static bool sUsing360;
};
bool LLAdvancedToggleInterestList360Mode::sUsing360 = false;
class LLAdvancedCheckInterestList360Mode : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
return LLAdvancedToggleInterestList360Mode::sUsing360;
}
};
class LLAdvancedToggleStatsRecorder : public view_listener_t
{
bool handleEvent(const LLSD &userdata)
{
if (LLViewerStatsRecorder::instance().isEnabled())
{ // Turn off both recording and logging
LLViewerStatsRecorder::instance().enableObjectStatsRecording(false);
}
else
{ // Turn on both recording and logging
LLViewerStatsRecorder::instance().enableObjectStatsRecording(true, true);
}
return true;
}
};
class LLAdvancedCheckStatsRecorder : public view_listener_t
{
bool handleEvent(const LLSD &userdata)
{ // Use the logging state as the indicator of whether the stats recorder is on
return LLViewerStatsRecorder::instance().isLogging();
}
};
class LLAdvancedBuyCurrencyTest : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -4492,33 +4543,6 @@ void handle_duplicate_in_place(void*)
LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE);
}
/* dead code 30-apr-2008
void handle_deed_object_to_group(void*)
{
LLUUID group_id;
LLSelectMgr::getInstance()->selectGetGroup(group_id);
LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE);
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT);
}
BOOL enable_deed_object_to_group(void*)
{
if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) return FALSE;
LLPermissions perm;
LLUUID group_id;
if (LLSelectMgr::getInstance()->selectGetGroup(group_id) &&
gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) &&
LLSelectMgr::getInstance()->selectGetPermissions(perm) &&
perm.deedToGroup(gAgent.getID(), group_id))
{
return TRUE;
}
return FALSE;
}
*/
/*
@ -9469,7 +9493,10 @@ void initialize_menus()
// Advanced > World
view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera");
view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
view_listener_t::addMenu(new LLAdvancedInterestListFullUpdate(), "Advanced.InterestListFullUpdate");
view_listener_t::addMenu(new LLAdvancedToggleInterestList360Mode(), "Advanced.ToggleInterestList360Mode");
view_listener_t::addMenu(new LLAdvancedCheckInterestList360Mode(), "Advanced.CheckInterestList360Mode");
view_listener_t::addMenu(new LLAdvancedToggleStatsRecorder(), "Advanced.ToggleStatsRecorder");
view_listener_t::addMenu(new LLAdvancedCheckStatsRecorder(), "Advanced.CheckStatsRecorder");
// Advanced > UI
commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser

View File

@ -369,7 +369,7 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry*
if (!objectp)
{
LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL;
recorder.objectUpdateFailure(entry->getLocalID(), OUT_FULL_CACHED, 0);
recorder.objectUpdateFailure(0);
return NULL;
}
justCreated = true;
@ -393,7 +393,6 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry*
objectp->setLastUpdateType(OUT_FULL_COMPRESSED); //newly cached
objectp->setLastUpdateCached(TRUE);
}
recorder.log(0.2f);
LLVOAvatar::cullAvatarsByPixelArea();
return objectp;
@ -472,18 +471,15 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
for (i = 0; i < num_objects; i++)
{
// timer is unused?
LLTimer update_timer;
BOOL justCreated = FALSE;
S32 msg_size = 0;
bool update_cache = false; //update object cache if it is a full-update or terse update
if (compressed)
{
S32 uncompressed_length = 2048;
compressed_dp.reset();
uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
S32 uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
LL_DEBUGS("ObjectUpdate") << "got binary data from message to compressed_dpbuffer" << LL_ENDL;
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i, 2048);
compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
@ -505,7 +501,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
<< " Flags: " << flags
<< " Region: " << regionp->getName()
<< " Region id: " << regionp->getRegionID() << LL_ENDL;
recorder.objectUpdateFailure(local_id, update_type, msg_size);
recorder.objectUpdateFailure(msg_size);
continue;
}
else if ((flags & FLAGS_TEMPORARY_ON_REZ) == 0)
@ -616,7 +612,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
if (update_type == OUT_TERSE_IMPROVED)
{
// LL_INFOS() << "terse update for an unknown object (compressed):" << fullid << LL_ENDL;
recorder.objectUpdateFailure(local_id, update_type, msg_size);
recorder.objectUpdateFailure(msg_size);
continue;
}
}
@ -625,7 +621,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
if (update_type != OUT_FULL)
{
//LL_INFOS() << "terse update for an unknown object:" << fullid << LL_ENDL;
recorder.objectUpdateFailure(local_id, update_type, msg_size);
recorder.objectUpdateFailure(msg_size);
continue;
}
@ -638,7 +634,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{
mNumDeadObjectUpdates++;
//LL_INFOS() << "update for a dead object:" << fullid << LL_ENDL;
recorder.objectUpdateFailure(local_id, update_type, msg_size);
recorder.objectUpdateFailure(msg_size);
continue;
}
#endif
@ -651,7 +647,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
if (!objectp)
{
LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL;
recorder.objectUpdateFailure(local_id, update_type, msg_size);
recorder.objectUpdateFailure(msg_size);
continue;
}
@ -681,11 +677,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
if(!(flags & FLAGS_TEMPORARY_ON_REZ))
{
bCached = true;
bCached = true;
LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags);
recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size);
recorder.cacheFullUpdate(result);
}
}
}
#endif
}
else
@ -696,12 +692,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);
}
recorder.objectUpdateEvent(local_id, update_type, objectp, msg_size);
recorder.objectUpdateEvent(update_type);
objectp->setLastUpdateType(update_type);
}
recorder.log(0.2f);
LLVOAvatar::cullAvatarsByPixelArea();
}
@ -748,14 +742,14 @@ void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
// Lookup data packer and add this id to cache miss lists if necessary.
U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
if(!regionp->probeCache(id, crc, flags, cache_miss_type))
{
// Cache Miss.
if (regionp->probeCache(id, crc, flags, cache_miss_type))
{ // Cache Hit
recorder.cacheHitEvent();
}
else
{ // Cache Miss
LL_DEBUGS("ObjectUpdate") << "cache miss for id " << id << " crc " << crc << " miss type " << (S32) cache_miss_type << LL_ENDL;
recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size);
continue; // no data packer, skip this object
recorder.cacheMissEvent(cache_miss_type);
}
}

View File

@ -2622,14 +2622,10 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id, bool valid)
return NULL;
}
void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type)
void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType cache_miss_type)
{
mRegionCacheMissCount++;
#if 0
mCacheMissList.insert(CacheMissItem(id, miss_type));
#else
mCacheMissList.push_back(CacheMissItem(id, miss_type));
#endif
mCacheMissList.push_back(CacheMissItem(id, cache_miss_type));
}
//check if a non-cacheable object is already created.
@ -2705,10 +2701,10 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
}
}
else
{
{ // Total miss, don't have the object in cache
// LL_INFOS() << "Cache miss for " << local_id << LL_ENDL;
addCacheMiss(local_id, CACHE_MISS_TYPE_FULL);
cache_miss_type = CACHE_MISS_TYPE_FULL;
addCacheMiss(local_id, CACHE_MISS_TYPE_TOTAL);
cache_miss_type = CACHE_MISS_TYPE_TOTAL;
}
return false;
@ -2716,7 +2712,7 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
void LLViewerRegion::addCacheMissFull(const U32 local_id)
{
addCacheMiss(local_id, CACHE_MISS_TYPE_FULL);
addCacheMiss(local_id, CACHE_MISS_TYPE_TOTAL);
}
void LLViewerRegion::requestCacheMisses()
@ -2767,7 +2763,6 @@ void LLViewerRegion::requestCacheMisses()
mCacheDirty = TRUE ;
// LL_INFOS() << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << LL_ENDL;
LLViewerStatsRecorder::instance().requestCacheMissesEvent(mCacheMissList.size());
LLViewerStatsRecorder::instance().log(0.2f);
mCacheMissList.clear();
}

View File

@ -332,9 +332,9 @@ public:
typedef enum
{
CACHE_MISS_TYPE_FULL = 0,
CACHE_MISS_TYPE_CRC,
CACHE_MISS_TYPE_NONE
CACHE_MISS_TYPE_TOTAL = 0, // total cache miss - object not in cache
CACHE_MISS_TYPE_CRC, // object in cache, but CRC doesn't match
CACHE_MISS_TYPE_NONE // not a miss: cache hit
} eCacheMissType;
typedef enum
@ -551,10 +551,10 @@ private:
class CacheMissItem
{
public:
CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type) : mID(id), mType(miss_type){}
CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type) : mID(id), mType(miss_type) {}
U32 mID; //local object id
LLViewerRegion::eCacheMissType mType; //cache miss type
U32 mID; //local object id
LLViewerRegion::eCacheMissType mType; // cache miss type
typedef std::list<CacheMissItem> cache_miss_list_t;
};

View File

@ -28,24 +28,25 @@
#include "llviewerstatsrecorder.h"
#include "llcontrol.h"
#include "llfile.h"
#include "llviewerregion.h"
#include "llviewerobject.h"
#include "llworld.h"
// To do - something using region name or global position
#if LL_WINDOWS
static const std::string STATS_FILE_NAME("C:\\ViewerObjectCacheStats.csv");
#else
static const std::string STATS_FILE_NAME("/tmp/viewerstats.csv");
#endif
extern LLControlGroup gSavedSettings;
LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL;
LLViewerStatsRecorder::LLViewerStatsRecorder() :
mObjectCacheFile(NULL),
mStatsFile(NULL),
mTimer(),
mStartTime(0.0),
mLastSnapshotTime(0.0)
mFileOpenTime(0.0),
mLastSnapshotTime(0.0),
mEnableStatsRecording(false),
mEnableStatsLogging(false),
mInterval(0.2),
mMaxDuration(300.f),
mSkipSaveIfZeros(false)
{
if (NULL != sInstance)
{
@ -57,79 +58,84 @@ LLViewerStatsRecorder::LLViewerStatsRecorder() :
LLViewerStatsRecorder::~LLViewerStatsRecorder()
{
if (mObjectCacheFile != NULL)
if (mStatsFile)
{
// last chance snapshot
writeToLog(0.f);
LLFile::close(mObjectCacheFile);
mObjectCacheFile = NULL;
writeToLog(0.f); // Save last data
closeStatsFile();
}
}
void LLViewerStatsRecorder::clearStats()
{
mObjectCacheHitCount = 0;
mObjectCacheHitSize = 0;
mObjectCacheMissFullCount = 0;
mObjectCacheMissFullSize = 0;
mObjectCacheMissCrcCount = 0;
mObjectCacheMissCrcSize = 0;
mObjectFullUpdates = 0;
mObjectFullUpdatesSize = 0;
mObjectTerseUpdates = 0;
mObjectTerseUpdatesSize = 0;
mObjectCacheMissRequests = 0;
mObjectCacheMissResponses = 0;
mObjectCacheMissResponsesSize = 0;
mObjectCacheUpdateDupes = 0;
mObjectCacheUpdateChanges = 0;
mObjectCacheUpdateAdds = 0;
mObjectCacheUpdateReplacements = 0;
mObjectUpdateFailures = 0;
mObjectUpdateFailuresSize = 0;
mTextureFetchSize = 0;
mTextureFetchCount = 0;
mMeshLoadedCount = 0;
}
void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size)
void LLViewerStatsRecorder::enableObjectStatsRecording(bool enable, bool logging /* false */)
{
mEnableStatsRecording = enable;
// if logging is stopping, close the file
if (mStatsFile && !logging)
{
writeToLog(0.f); // Save last data
closeStatsFile();
}
mEnableStatsLogging = logging;
}
void LLViewerStatsRecorder::recordObjectUpdateFailure(S32 msg_size)
{
mObjectUpdateFailures++;
mObjectUpdateFailuresSize += msg_size;
}
void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size)
void LLViewerStatsRecorder::recordCacheMissEvent(U8 cache_miss_type)
{
if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type)
if (LLViewerRegion::CACHE_MISS_TYPE_TOTAL == cache_miss_type)
{
mObjectCacheMissFullCount++;
mObjectCacheMissFullSize += msg_size;
}
else
{
mObjectCacheMissCrcCount++;
mObjectCacheMissCrcSize += msg_size;
}
}
void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size)
void LLViewerStatsRecorder::recordCacheHitEvent()
{
switch (update_type)
mObjectCacheHitCount++;
}
void LLViewerStatsRecorder::recordObjectUpdateEvent(const EObjectUpdateType update_type)
{
switch (update_type)
{
case OUT_FULL:
mObjectFullUpdates++;
mObjectFullUpdatesSize += msg_size;
break;
case OUT_TERSE_IMPROVED:
mObjectTerseUpdates++;
mObjectTerseUpdatesSize += msg_size;
break;
case OUT_FULL_COMPRESSED:
mObjectCacheMissResponses++;
mObjectCacheMissResponsesSize += msg_size;
break;
case OUT_FULL_CACHED:
mObjectCacheHitCount++;
mObjectCacheHitSize += msg_size;
break;
default:
LL_WARNS() << "Unknown update_type" << LL_ENDL;
@ -137,9 +143,9 @@ void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectU
};
}
void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size)
void LLViewerStatsRecorder::recordCacheFullUpdate(LLViewerRegion::eCacheUpdateResult update_result)
{
switch (update_result)
switch (update_result)
{
case LLViewerRegion::CACHE_UPDATE_DUPE:
mObjectCacheUpdateDupes++;
@ -154,7 +160,7 @@ void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpd
mObjectCacheUpdateReplacements++;
break;
default:
LL_WARNS() << "Unknown update_result type" << LL_ENDL;
LL_WARNS() << "Unknown update_result type " << (S32) update_result << LL_ENDL;
break;
};
}
@ -166,14 +172,30 @@ void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count)
void LLViewerStatsRecorder::writeToLog( F32 interval )
{
if (!mEnableStatsLogging || !mEnableStatsRecording)
{
return;
}
size_t data_size = 0;
F64 delta_time = LLTimer::getTotalSeconds() - mLastSnapshotTime;
S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures;
F64 delta_time = LLFrameTimer::getTotalSeconds() - mLastSnapshotTime;
if (delta_time < interval)
return;
if ( delta_time < interval || total_objects == 0) return;
if (mSkipSaveIfZeros)
{
S32 total_events = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates +
mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes +
mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures;
if (total_events == 0)
{
LL_DEBUGS("ILXZeroData") << "ILX: not saving zero data" << LL_ENDL;
return;
}
}
mLastSnapshotTime = LLTimer::getTotalSeconds();
LL_DEBUGS() << "ILX: "
mLastSnapshotTime = LLFrameTimer::getTotalSeconds();
LL_DEBUGS("ILX") << "ILX: "
<< mObjectCacheHitCount << " hits, "
<< mObjectCacheMissFullCount << " full misses, "
<< mObjectCacheMissCrcCount << " crc misses, "
@ -188,90 +210,136 @@ void LLViewerStatsRecorder::writeToLog( F32 interval )
<< mObjectUpdateFailures << " update failures"
<< LL_ENDL;
if (mObjectCacheFile == NULL)
if (mStatsFile == NULL)
{
mStartTime = LLTimer::getTotalSeconds();
mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb");
if (mObjectCacheFile)
{ // Write column headers
std::ostringstream data_msg;
data_msg << "EventTime(ms)\t"
<< "Cache Hits\t"
<< "Cache Full Misses\t"
<< "Cache Crc Misses\t"
<< "Full Updates\t"
<< "Terse Updates\t"
<< "Cache Miss Requests\t"
<< "Cache Miss Responses\t"
<< "Cache Update Dupes\t"
<< "Cache Update Changes\t"
<< "Cache Update Adds\t"
<< "Cache Update Replacements\t"
<< "Update Failures\t"
<< "Cache Hits bps\t"
<< "Cache Full Misses bps\t"
<< "Cache Crc Misses bps\t"
<< "Full Updates bps\t"
<< "Terse Updates bps\t"
<< "Cache Miss Responses bps\t"
<< "Texture Fetch bps\t"
<< "\n";
// Refresh settings
mInterval = gSavedSettings.getF32("StatsReportFileInterval");
mSkipSaveIfZeros = gSavedSettings.getBOOL("StatsReportSkipZeroDataSaves");
mMaxDuration = gSavedSettings.getF32("StatsReportMaxDuration");
data_size = data_msg.str().size();
if (fwrite(data_msg.str().c_str(), 1, data_size, mObjectCacheFile ) != data_size)
// Open the data file
makeStatsFileName();
mStatsFile = LLFile::fopen(mStatsFileName, "wb");
if (mStatsFile)
{
LL_INFOS("ILX") << "ILX: Writing update information to " << mStatsFileName << LL_ENDL;
mFileOpenTime = LLFrameTimer::getTotalSeconds();
// Write column headers
std::ostringstream col_headers;
col_headers << "Time (sec),"
<< "Regions,"
<< "Active Cached Objects,"
<< "Cache Hits,"
<< "Cache Full Misses,"
<< "Cache Crc Misses,"
<< "Full Updates,"
<< "Terse Updates,"
<< "Cache Miss Requests,"
<< "Cache Miss Responses,"
<< "Cache Update Dupes,"
<< "Cache Update Changes,"
<< "Cache Update Adds,"
<< "Cache Update Replacements,"
<< "Update Failures,"
<< "Texture Count,"
<< "Mesh Load Count,"
<< "\n";
data_size = col_headers.str().size();
if (fwrite(col_headers.str().c_str(), 1, data_size, mStatsFile ) != data_size)
{
LL_WARNS() << "failed to write full headers to " << STATS_FILE_NAME << LL_ENDL;
LL_WARNS() << "failed to write full headers to " << mStatsFileName << LL_ENDL;
}
}
else
{
//LL_WARNS() << "Couldn't open " << STATS_FILE_NAME << " for logging." << LL_ENDL;
{ // Failed to open file
LL_WARNS() << "Couldn't open " << mStatsFileName << " for logging, turning off stats recording." << LL_ENDL;
mEnableStatsLogging = false;
return;
}
}
std::ostringstream data_msg;
std::ostringstream stats_data;
data_msg << getTimeSinceStart()
<< "\t " << mObjectCacheHitCount
<< "\t" << mObjectCacheMissFullCount
<< "\t" << mObjectCacheMissCrcCount
<< "\t" << mObjectFullUpdates
<< "\t" << mObjectTerseUpdates
<< "\t" << mObjectCacheMissRequests
<< "\t" << mObjectCacheMissResponses
<< "\t" << mObjectCacheUpdateDupes
<< "\t" << mObjectCacheUpdateChanges
<< "\t" << mObjectCacheUpdateAdds
<< "\t" << mObjectCacheUpdateReplacements
<< "\t" << mObjectUpdateFailures
<< "\t" << (mObjectCacheHitSize * 8 / delta_time)
<< "\t" << (mObjectCacheMissFullSize * 8 / delta_time)
<< "\t" << (mObjectCacheMissCrcSize * 8 / delta_time)
<< "\t" << (mObjectFullUpdatesSize * 8 / delta_time)
<< "\t" << (mObjectTerseUpdatesSize * 8 / delta_time)
<< "\t" << (mObjectCacheMissResponsesSize * 8 / delta_time)
<< "\t" << (mTextureFetchSize * 8 / delta_time)
stats_data << getTimeSinceStart()
<< "," << LLWorld::getInstance()->getRegionList().size()
<< "," << LLWorld::getInstance()->getNumOfActiveCachedObjects()
<< "," << mObjectCacheHitCount
<< "," << mObjectCacheMissFullCount
<< "," << mObjectCacheMissCrcCount
<< "," << mObjectFullUpdates
<< "," << mObjectTerseUpdates
<< "," << mObjectCacheMissRequests
<< "," << mObjectCacheMissResponses
<< "," << mObjectCacheUpdateDupes
<< "," << mObjectCacheUpdateChanges
<< "," << mObjectCacheUpdateAdds
<< "," << mObjectCacheUpdateReplacements
<< "," << mObjectUpdateFailures
<< "," << mTextureFetchCount
<< "," << mMeshLoadedCount
<< "\n";
data_size = data_msg.str().size();
if ( data_size != fwrite(data_msg.str().c_str(), 1, data_size, mObjectCacheFile ))
data_size = stats_data.str().size();
if ( data_size != fwrite(stats_data.str().c_str(), 1, data_size, mStatsFile ))
{
LL_WARNS() << "Unable to write complete column data to " << STATS_FILE_NAME << LL_ENDL;
}
LL_WARNS() << "Unable to write complete column data to " << mStatsFileName << LL_ENDL;
closeStatsFile();
}
clearStats();
if (getTimeSinceStart() >= mMaxDuration)
{ // If file recording has been running for too long, stop it.
closeStatsFile();
}
}
void LLViewerStatsRecorder::closeStatsFile()
{
if (mStatsFile)
{
LL_INFOS("ILX") << "ILX: Stopped writing update information to " << mStatsFileName << " after " << getTimeSinceStart()
<< " seconds." << LL_ENDL;
LLFile::close(mStatsFile);
mStatsFile = NULL;
}
mEnableStatsLogging = false;
}
void LLViewerStatsRecorder::makeStatsFileName()
{
// Create filename - tbd: use pid?
#if LL_WINDOWS
std::string stats_file_name("SLViewerStats-");
#else
std::string stats_file_name("slviewerstats-");
#endif
F64 now = LLFrameTimer::getTotalSeconds();
std::string date_str = LLDate(now).asString();
std::replace(date_str.begin(), date_str.end(), ':', '-'); // Make it valid for a filename
stats_file_name.append(date_str);
stats_file_name.append(".csv");
mStatsFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, stats_file_name);
}
F32 LLViewerStatsRecorder::getTimeSinceStart()
{
return (F32) (LLTimer::getTotalSeconds() - mStartTime);
return (F32) (LLFrameTimer::getTotalSeconds() - mFileOpenTime);
}
void LLViewerStatsRecorder::recordTextureFetch( S32 msg_size )
void LLViewerStatsRecorder::recordTextureFetch()
{
mTextureFetchSize += msg_size;
mTextureFetchCount += 1;
}
void LLViewerStatsRecorder::recordMeshLoaded()
{
mMeshLoadedCount += 1;
}

View File

@ -31,10 +31,6 @@
// This is a diagnostic class used to record information from the viewer
// for analysis.
// This is normally 0. Set to 1 to enable viewer stats recording
#define LL_RECORD_VIEWER_STATS 0
#include "llframetimer.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
@ -49,97 +45,130 @@ class LLViewerStatsRecorder : public LLSingleton<LLViewerStatsRecorder>
~LLViewerStatsRecorder();
public:
void objectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size)
{
#if LL_RECORD_VIEWER_STATS
recordObjectUpdateFailure(local_id, update_type, msg_size);
#endif
// Enable/disable stats recording. This is broken down into two
// flags so we can record stats without writing them to the log
// file. This is useful to analyzing updates for scene loading.
void enableObjectStatsRecording(bool enable, bool logging = false);
bool isEnabled() const { return mEnableStatsRecording; }
bool isLogging() const { return mEnableStatsLogging; }
void objectUpdateFailure(S32 msg_size)
{
if (mEnableStatsRecording)
{
recordObjectUpdateFailure(msg_size);
}
}
void cacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size)
void cacheMissEvent(U8 cache_miss_type)
{
#if LL_RECORD_VIEWER_STATS
recordCacheMissEvent(local_id, update_type, cache_miss_type, msg_size);
#endif
if (mEnableStatsRecording)
{
recordCacheMissEvent(cache_miss_type);
}
}
void cacheHitEvent()
{
if (mEnableStatsRecording)
{
recordCacheHitEvent();
}
}
void objectUpdateEvent(const EObjectUpdateType update_type)
{
if (mEnableStatsRecording)
{
recordObjectUpdateEvent(update_type);
}
}
void objectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size)
{
#if LL_RECORD_VIEWER_STATS
recordObjectUpdateEvent(local_id, update_type, objectp, msg_size);
#endif
}
void cacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size)
{
#if LL_RECORD_VIEWER_STATS
recordCacheFullUpdate(local_id, update_type, update_result, objectp, msg_size);
#endif
void cacheFullUpdate(LLViewerRegion::eCacheUpdateResult update_result)
{
if (mEnableStatsRecording)
{
recordCacheFullUpdate(update_result);
}
}
void requestCacheMissesEvent(S32 count)
{
#if LL_RECORD_VIEWER_STATS
recordRequestCacheMissesEvent(count);
#endif
if (mEnableStatsRecording)
{
recordRequestCacheMissesEvent(count);
}
}
void textureFetch(S32 msg_size)
void textureFetch()
{
#if LL_RECORD_VIEWER_STATS
recordTextureFetch(msg_size);
#endif
if (mEnableStatsRecording)
{
recordTextureFetch();
}
}
void log(F32 interval)
void meshLoaded()
{
#if LL_RECORD_VIEWER_STATS
writeToLog(interval);
#endif
if (mEnableStatsRecording)
{
recordMeshLoaded();
}
}
void idle()
{
writeToLog(mInterval);
}
F32 getTimeSinceStart();
private:
void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size);
void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size);
void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size);
void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size);
void recordObjectUpdateFailure(S32 msg_size);
void recordCacheMissEvent(U8 cache_miss_type);
void recordCacheHitEvent();
void recordObjectUpdateEvent(const EObjectUpdateType update_type);
void recordCacheFullUpdate(LLViewerRegion::eCacheUpdateResult update_result);
void recordRequestCacheMissesEvent(S32 count);
void recordTextureFetch(S32 msg_size);
void recordTextureFetch();
void recordMeshLoaded();
void writeToLog(F32 interval);
void closeStatsFile();
void makeStatsFileName();
static LLViewerStatsRecorder* sInstance;
LLFILE * mObjectCacheFile; // File to write data into
LLFILE * mStatsFile; // File to write data into
std::string mStatsFileName;
LLFrameTimer mTimer;
F64 mStartTime;
F64 mFileOpenTime;
F64 mLastSnapshotTime;
F32 mInterval; // Interval between data log writes
F32 mMaxDuration; // Time limit on file
bool mEnableStatsRecording; // Set to true to enable recording stats data
bool mEnableStatsLogging; // Set true to write stats to log file
bool mSkipSaveIfZeros; // Set true to skip saving stats if all values are zero
S32 mObjectCacheHitCount;
S32 mObjectCacheHitSize;
S32 mObjectCacheMissFullCount;
S32 mObjectCacheMissFullSize;
S32 mObjectCacheMissCrcCount;
S32 mObjectCacheMissCrcSize;
S32 mObjectFullUpdates;
S32 mObjectFullUpdatesSize;
S32 mObjectTerseUpdates;
S32 mObjectTerseUpdatesSize;
S32 mObjectCacheMissRequests;
S32 mObjectCacheMissResponses;
S32 mObjectCacheMissResponsesSize;
S32 mObjectCacheUpdateDupes;
S32 mObjectCacheUpdateChanges;
S32 mObjectCacheUpdateAdds;
S32 mObjectCacheUpdateReplacements;
S32 mObjectUpdateFailures;
S32 mObjectUpdateFailuresSize;
S32 mTextureFetchSize;
S32 mTextureFetchCount;
S32 mMeshLoadedCount;
void clearStats();
};
#endif // LLVIEWERSTATSRECORDER_H

View File

@ -3485,14 +3485,24 @@ function="World.EnvPreset"
<menu_item_call.on_click
function="Advanced.DumpRegionObjectCache" />
</menu_item_call>
<menu_item_call
label="Interest List: Full Update"
name="Interest List: Full Update"
<menu_item_check
label="Interest List 360 Mode"
name="Interest List: 360 Mode"
shortcut="alt|shift|I">
<menu_item_call.on_click
function="Advanced.InterestListFullUpdate" />
</menu_item_call>
<menu_item_check.on_check
function="Advanced.CheckInterestList360Mode" />
<menu_item_check.on_click
function="Advanced.ToggleInterestList360Mode" />
</menu_item_check>
<menu_item_check
label="Record Stats to File"
name="Stats Recorder File">
<menu_item_check.on_check
function="Advanced.CheckStatsRecorder" />
<menu_item_check.on_click
function="Advanced.ToggleStatsRecorder" />
</menu_item_check>
</menu>
<menu
create_jump_keys="true"