summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerassetstats.cpp
diff options
context:
space:
mode:
authorRichard Linden <none@none>2013-01-04 16:46:25 -0800
committerRichard Linden <none@none>2013-01-04 16:46:25 -0800
commit0d8f1077a62099915cb532dc354d0e450e3e6a79 (patch)
treef76f43d025304bc6aa65d3f91663cac67a6715cc /indra/newview/llviewerassetstats.cpp
parent0d12d171cf20c63a45e7ad0989e65d05aabb86ea (diff)
parent7dbb8860373769dfca7d6c6588284866a1bf86a3 (diff)
Automated merge with http://bitbucket.org/lindenlab/viewer-development
Diffstat (limited to 'indra/newview/llviewerassetstats.cpp')
-rw-r--r--indra/newview/llviewerassetstats.cpp841
1 files changed, 402 insertions, 439 deletions
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index 4c59fd0371..58936c3220 100644
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -31,6 +31,8 @@
#include "stdtypes.h"
#include "llvoavatar.h"
+#include "llsdparam.h"
+#include "llsdutil.h"
/*
* Classes and utility functions for per-thread and per-region
@@ -78,128 +80,226 @@
*
*/
+namespace LLViewerAssetStatsFF
+{
+ static EViewerAssetCategories asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp)
+ {
+ // For statistical purposes, we divide GETs into several
+ // populations of asset fetches:
+ // - textures which are de-prioritized in the asset system
+ // - wearables (clothing, bodyparts) which directly affect
+ // user experiences when they log in
+ // - sounds
+ // - gestures
+ // - everything else.
+ //
+ llassert_always(50 == LLViewerAssetType::AT_COUNT);
+
+ // Multiple asset definitions are floating around so this requires some
+ // maintenance and attention.
+ static const EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] =
+ {
+ EVACTextureTempHTTPGet, // (0) AT_TEXTURE
+ EVACSoundUDPGet, // AT_SOUND
+ EVACOtherGet, // AT_CALLINGCARD
+ EVACOtherGet, // AT_LANDMARK
+ EVACOtherGet, // AT_SCRIPT
+ EVACWearableUDPGet, // AT_CLOTHING
+ EVACOtherGet, // AT_OBJECT
+ EVACOtherGet, // AT_NOTECARD
+ EVACOtherGet, // AT_CATEGORY
+ EVACOtherGet, // AT_ROOT_CATEGORY
+ EVACOtherGet, // (10) AT_LSL_TEXT
+ EVACOtherGet, // AT_LSL_BYTECODE
+ EVACOtherGet, // AT_TEXTURE_TGA
+ EVACWearableUDPGet, // AT_BODYPART
+ EVACOtherGet, // AT_TRASH
+ EVACOtherGet, // AT_SNAPSHOT_CATEGORY
+ EVACOtherGet, // AT_LOST_AND_FOUND
+ EVACSoundUDPGet, // AT_SOUND_WAV
+ EVACOtherGet, // AT_IMAGE_TGA
+ EVACOtherGet, // AT_IMAGE_JPEG
+ EVACGestureUDPGet, // (20) AT_ANIMATION
+ EVACGestureUDPGet, // AT_GESTURE
+ EVACOtherGet, // AT_SIMSTATE
+ EVACOtherGet, // AT_FAVORITE
+ EVACOtherGet, // AT_LINK
+ EVACOtherGet, // AT_LINK_FOLDER
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, // (30)
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, // (40)
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, //
+ EVACOtherGet, // AT_MESH
+ // (50)
+ };
-// ------------------------------------------------------
-// Global data definitions
-// ------------------------------------------------------
-LLViewerAssetStats * gViewerAssetStatsMain(0);
-LLViewerAssetStats * gViewerAssetStatsThread1(0);
+ if (at < 0 || at >= LLViewerAssetType::AT_COUNT)
+ {
+ return EVACOtherGet;
+ }
+ EViewerAssetCategories ret(asset_to_bin_map[at]);
+ if (EVACTextureTempHTTPGet == ret)
+ {
+ // Indexed with [is_temp][with_http]
+ static const EViewerAssetCategories texture_bin_map[2][2] =
+ {
+ {
+ EVACTextureNonTempUDPGet,
+ EVACTextureNonTempHTTPGet,
+ },
+ {
+ EVACTextureTempUDPGet,
+ EVACTextureTempHTTPGet,
+ }
+ };
+ ret = texture_bin_map[is_temp][with_http];
+ }
+ return ret;
+ }
+ static LLTrace::Count<> sEnqueued[EVACCount] = {LLTrace::Count<>("enqueuedassetrequeststemptexturehttp",
+ "Number of temporary texture asset http requests enqueued"),
+ LLTrace::Count<>("enqueuedassetrequeststemptextureudp",
+ "Number of temporary texture asset udp requests enqueued"),
+ LLTrace::Count<>("enqueuedassetrequestsnontemptexturehttp",
+ "Number of texture asset http requests enqueued"),
+ LLTrace::Count<>("enqueuedassetrequestsnontemptextureudp",
+ "Number of texture asset udp requests enqueued"),
+ LLTrace::Count<>("enqueuedassetrequestswearableudp",
+ "Number of wearable asset requests enqueued"),
+ LLTrace::Count<>("enqueuedassetrequestssoundudp",
+ "Number of sound asset requests enqueued"),
+ LLTrace::Count<>("enqueuedassetrequestsgestureudp",
+ "Number of gesture asset requests enqueued"),
+ LLTrace::Count<>("enqueuedassetrequestsother",
+ "Number of other asset requests enqueued")};
+
+ static LLTrace::Count<> sDequeued[EVACCount] = {LLTrace::Count<>("dequeuedassetrequeststemptexturehttp",
+ "Number of temporary texture asset http requests dequeued"),
+ LLTrace::Count<>("dequeuedassetrequeststemptextureudp",
+ "Number of temporary texture asset udp requests dequeued"),
+ LLTrace::Count<>("dequeuedassetrequestsnontemptexturehttp",
+ "Number of texture asset http requests dequeued"),
+ LLTrace::Count<>("dequeuedassetrequestsnontemptextureudp",
+ "Number of texture asset udp requests dequeued"),
+ LLTrace::Count<>("dequeuedassetrequestswearableudp",
+ "Number of wearable asset requests dequeued"),
+ LLTrace::Count<>("dequeuedassetrequestssoundudp",
+ "Number of sound asset requests dequeued"),
+ LLTrace::Count<>("dequeuedassetrequestsgestureudp",
+ "Number of gesture asset requests dequeued"),
+ LLTrace::Count<>("dequeuedassetrequestsother",
+ "Number of other asset requests dequeued")};
+ static LLTrace::Measurement<LLTrace::Seconds> sResponse[EVACCount] = {LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimestemptexturehttp",
+ "Time spent responding to temporary texture asset http requests"),
+ LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimestemptextureudp",
+ "Time spent responding to temporary texture asset udp requests"),
+ LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimesnontemptexturehttp",
+ "Time spent responding to texture asset http requests"),
+ LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimesnontemptextureudp",
+ "Time spent responding to texture asset udp requests"),
+ LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimeswearableudp",
+ "Time spent responding to wearable asset requests"),
+ LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimessoundudp",
+ "Time spent responding to sound asset requests"),
+ LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimesgestureudp",
+ "Time spent responding to gesture asset requests"),
+ LLTrace::Measurement<LLTrace::Seconds>("assetresponsetimesother",
+ "Time spent responding to other asset requests")};
+}
// ------------------------------------------------------
-// Local declarations
+// Global data definitions
// ------------------------------------------------------
-namespace
-{
-
-static LLViewerAssetStats::EViewerAssetCategories
-asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp);
-
-}
+LLViewerAssetStats * gViewerAssetStats(0);
// ------------------------------------------------------
-// LLViewerAssetStats::PerRegionStats struct definition
+// LLViewerAssetStats class definition
// ------------------------------------------------------
-void
-LLViewerAssetStats::PerRegionStats::reset()
+LLViewerAssetStats::LLViewerAssetStats()
+: mRegionHandle(U64(0)),
+ mCurRecording(NULL)
{
- for (int i(0); i < LL_ARRAY_SIZE(mRequests); ++i)
- {
- mRequests[i].mEnqueued.reset();
- mRequests[i].mDequeued.reset();
- mRequests[i].mResponse.reset();
- }
- mFPS.reset();
-
- mTotalTime = 0;
- mStartTimestamp = LLViewerAssetStatsFF::get_timestamp();
+ start();
}
-void
-LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionStats & src)
+LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src)
+: mRegionHandle(src.mRegionHandle),
+ mPhaseStats(src.mPhaseStats),
+ mAvatarRezStates(src.mAvatarRezStates)
{
- // mRegionHandle, mTotalTime, mStartTimestamp are left alone.
-
- // mFPS
- if (src.mFPS.getCount() && mFPS.getCount())
- {
- mFPS.merge(src.mFPS);
- }
+ src.mCurRecording->update();
+ mRegionRecordings = src.mRegionRecordings;
- // Avatar stats - data all comes from main thread, so leave alone.
+ mCurRecording = &mRegionRecordings[mRegionHandle];
+ mCurRecording->stop();
- // Requests
- for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i)
+ // assume this is being passed to another thread, so make sure we have unique copies of recording data
+ for (PerRegionRecordingContainer::iterator it = mRegionRecordings.begin(), end_it = mRegionRecordings.end();
+ it != end_it;
+ ++it)
{
- mRequests[i].mEnqueued.merge(src.mRequests[i].mEnqueued);
- mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued);
- mRequests[i].mResponse.merge(src.mRequests[i].mResponse);
+ it->second.makeUnique();
}
+ LLStopWatchControlsMixin::initTo(src.getPlayState());
}
-
-void
-LLViewerAssetStats::PerRegionStats::accumulateTime(duration_t now)
+void LLViewerAssetStats::handleStart()
{
- mTotalTime += (now - mStartTimestamp);
- mStartTimestamp = now;
+ if (mCurRecording)
+ {
+ mCurRecording->start();
+ }
}
-
-// ------------------------------------------------------
-// LLViewerAssetStats class definition
-// ------------------------------------------------------
-LLViewerAssetStats::LLViewerAssetStats()
- : mRegionHandle(U64(0))
+void LLViewerAssetStats::handleStop()
{
- reset();
+ if (mCurRecording)
+ {
+ mCurRecording->stop();
+ }
}
-
-LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src)
- : mRegionHandle(src.mRegionHandle),
- mResetTimestamp(src.mResetTimestamp),
- mPhaseStats(src.mPhaseStats),
- mAvatarRezStates(src.mAvatarRezStates)
+void LLViewerAssetStats::handleReset()
{
- const PerRegionContainer::const_iterator it_end(src.mRegionStats.end());
- for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it)
- {
- mRegionStats[it->first] = new PerRegionStats(*it->second);
- }
- mCurRegionStats = mRegionStats[mRegionHandle];
+ reset();
}
-void
-LLViewerAssetStats::reset()
+void LLViewerAssetStats::reset()
{
// Empty the map of all region stats
- mRegionStats.clear();
+ mRegionRecordings.clear();
- // If we have a current stats, reset it, otherwise, as at construction,
- // create a new one as we must always have a current stats block.
- if (mCurRegionStats)
- {
- mCurRegionStats->reset();
- }
- else
+ // initialize new recording for current region
+ if (mRegionHandle)
{
- mCurRegionStats = new PerRegionStats(mRegionHandle);
+ mCurRecording = &mRegionRecordings[mRegionHandle];
}
-
- // And add reference to map
- mRegionStats[mRegionHandle] = mCurRegionStats;
-
- // Start timestamp consistent with per-region collector
- mResetTimestamp = mCurRegionStats->mStartTimestamp;
}
-
-void
-LLViewerAssetStats::setRegion(region_handle_t region_handle)
+void LLViewerAssetStats::setRegion(region_handle_t region_handle)
{
if (region_handle == mRegionHandle)
{
@@ -207,445 +307,308 @@ LLViewerAssetStats::setRegion(region_handle_t region_handle)
return;
}
- // Get duration for current set
- const duration_t now = LLViewerAssetStatsFF::get_timestamp();
- mCurRegionStats->accumulateTime(now);
-
- // Prepare new set
- PerRegionContainer::iterator new_stats = mRegionStats.find(region_handle);
- if (mRegionStats.end() == new_stats)
+ if (mCurRecording)
{
- // Haven't seen this region_id before, create a new block and make it current.
- mCurRegionStats = new PerRegionStats(region_handle);
- mRegionStats[region_handle] = mCurRegionStats;
+ mCurRecording->pause();
}
- else
+ if (region_handle)
{
- mCurRegionStats = new_stats->second;
+ mCurRecording = &mRegionRecordings[region_handle];
+ mCurRecording->start();
}
- mCurRegionStats->mStartTimestamp = now;
+
mRegionHandle = region_handle;
}
-
-void
-LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp)
-{
- const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
-
- ++(mCurRegionStats->mRequests[int(eac)].mEnqueued);
-}
-
-void
-LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+void LLViewerAssetStats::recordAvatarStats()
{
- const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
-
- ++(mCurRegionStats->mRequests[int(eac)].mDequeued);
+ LLVOAvatar::getNearbyRezzedStats(mAvatarRezStates);
+ mPhaseStats.clear();
+ mPhaseStats["cloud"] = LLViewerStats::PhaseMap::getPhaseStats("cloud");
+ mPhaseStats["cloud-or-gray"] = LLViewerStats::PhaseMap::getPhaseStats("cloud-or-gray");
}
-void
-LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration)
+void LLViewerAssetStats::updateStats()
{
- const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
-
- mCurRegionStats->mRequests[int(eac)].mResponse.record(duration);
+ if (mCurRecording && mCurRecording->isStarted())
+ {
+ mCurRecording->update();
+ }
}
-void
-LLViewerAssetStats::recordFPS(F32 fps)
+void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
{
- mCurRegionStats->mFPS.record(fps);
-}
+ using namespace LLViewerAssetStatsFF;
+
+ stats.regions.setProvided();
+
+ for (PerRegionRecordingContainer::iterator it = mRegionRecordings.begin(), end_it = mRegionRecordings.end();
+ it != end_it;
+ ++it)
+ {
+ RegionStats& r = stats.regions.add();
+ LLTrace::Recording& rec = it->second;
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACTextureTempHTTPGet])
+ || rec.getSum(sDequeued[EVACTextureTempHTTPGet])
+ || rec.getSum(sResponse[EVACTextureTempHTTPGet]).value())
+ {
+ r.get_texture_temp_http .enqueued(rec.getSum(sEnqueued[EVACTextureTempHTTPGet]))
+ .dequeued(rec.getSum(sDequeued[EVACTextureTempHTTPGet]))
+ .resp_count(rec.getSum(sResponse[EVACTextureTempHTTPGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACTextureTempHTTPGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACTextureTempHTTPGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACTextureTempHTTPGet]).value());
+ }
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACTextureTempUDPGet])
+ || rec.getSum(sDequeued[EVACTextureTempUDPGet])
+ || rec.getSum(sResponse[EVACTextureTempUDPGet]).value())
+ {
+ r.get_texture_temp_udp .enqueued(rec.getSum(sEnqueued[EVACTextureTempUDPGet]))
+ .dequeued(rec.getSum(sDequeued[EVACTextureTempUDPGet]))
+ .resp_count(rec.getSum(sResponse[EVACTextureTempUDPGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACTextureTempUDPGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACTextureTempUDPGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACTextureTempUDPGet]).value());
+ }
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACTextureNonTempHTTPGet])
+ || rec.getSum(sDequeued[EVACTextureNonTempHTTPGet])
+ || rec.getSum(sResponse[EVACTextureNonTempHTTPGet]).value())
+ {
+ r.get_texture_non_temp_http .enqueued(rec.getSum(sEnqueued[EVACTextureNonTempHTTPGet]))
+ .dequeued(rec.getSum(sDequeued[EVACTextureNonTempHTTPGet]))
+ .resp_count(rec.getSum(sResponse[EVACTextureNonTempHTTPGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACTextureNonTempHTTPGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACTextureNonTempHTTPGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACTextureNonTempHTTPGet]).value());
+ }
-void
-LLViewerAssetStats::recordAvatarStats()
-{
- std::vector<S32> rez_counts;
- LLVOAvatar::getNearbyRezzedStats(rez_counts);
- mAvatarRezStates = rez_counts;
- mPhaseStats.clear();
- mPhaseStats["cloud"] = LLViewerStats::PhaseMap::getPhaseStats("cloud");
- mPhaseStats["cloud-or-gray"] = LLViewerStats::PhaseMap::getPhaseStats("cloud-or-gray");
-}
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACTextureNonTempUDPGet])
+ || rec.getSum(sDequeued[EVACTextureNonTempUDPGet])
+ || rec.getSum(sResponse[EVACTextureNonTempUDPGet]).value())
+ {
+ r.get_texture_non_temp_udp .enqueued(rec.getSum(sEnqueued[EVACTextureNonTempUDPGet]))
+ .dequeued(rec.getSum(sDequeued[EVACTextureNonTempUDPGet]))
+ .resp_count(rec.getSum(sResponse[EVACTextureNonTempUDPGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACTextureNonTempUDPGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACTextureNonTempUDPGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACTextureNonTempUDPGet]).value());
+ }
-LLSD
-LLViewerAssetStats::asLLSD(bool compact_output)
-{
- // Top-level tags
- static const LLSD::String tags[EVACCount] =
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACWearableUDPGet])
+ || rec.getSum(sDequeued[EVACWearableUDPGet])
+ || rec.getSum(sResponse[EVACWearableUDPGet]).value())
{
- LLSD::String("get_texture_temp_http"),
- LLSD::String("get_texture_temp_udp"),
- LLSD::String("get_texture_non_temp_http"),
- LLSD::String("get_texture_non_temp_udp"),
- LLSD::String("get_wearable_udp"),
- LLSD::String("get_sound_udp"),
- LLSD::String("get_gesture_udp"),
- LLSD::String("get_other")
- };
+ r.get_wearable_udp .enqueued(rec.getSum(sEnqueued[EVACWearableUDPGet]))
+ .dequeued(rec.getSum(sDequeued[EVACWearableUDPGet]))
+ .resp_count(rec.getSum(sResponse[EVACWearableUDPGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACWearableUDPGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACWearableUDPGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACWearableUDPGet]).value());
+ }
- // Stats Group Sub-tags.
- static const LLSD::String enq_tag("enqueued");
- static const LLSD::String deq_tag("dequeued");
- static const LLSD::String rcnt_tag("resp_count");
- static const LLSD::String rmin_tag("resp_min");
- static const LLSD::String rmax_tag("resp_max");
- static const LLSD::String rmean_tag("resp_mean");
-
- // MMM Group Sub-tags.
- static const LLSD::String cnt_tag("count");
- static const LLSD::String min_tag("min");
- static const LLSD::String max_tag("max");
- static const LLSD::String mean_tag("mean");
-
- // Avatar sub-tags
- static const LLSD::String avatar_tag("avatar");
- static const LLSD::String avatar_nearby_tag("nearby");
- static const LLSD::String avatar_phase_stats_tag("phase_stats");
-
- const duration_t now = LLViewerAssetStatsFF::get_timestamp();
- mCurRegionStats->accumulateTime(now);
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACSoundUDPGet])
+ || rec.getSum(sDequeued[EVACSoundUDPGet])
+ || rec.getSum(sResponse[EVACSoundUDPGet]).value())
+ {
+ r.get_sound_udp .enqueued(rec.getSum(sEnqueued[EVACSoundUDPGet]))
+ .dequeued(rec.getSum(sDequeued[EVACSoundUDPGet]))
+ .resp_count(rec.getSum(sResponse[EVACSoundUDPGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACSoundUDPGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACSoundUDPGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACSoundUDPGet]).value());
+ }
- LLSD regions = LLSD::emptyArray();
- for (PerRegionContainer::iterator it = mRegionStats.begin();
- mRegionStats.end() != it;
- ++it)
- {
- if (0 == it->first)
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACGestureUDPGet])
+ || rec.getSum(sDequeued[EVACGestureUDPGet])
+ || rec.getSum(sResponse[EVACGestureUDPGet]).value())
{
- // Never emit NULL UUID/handle in results.
- continue;
+ r.get_gesture_udp .enqueued(rec.getSum(sEnqueued[EVACGestureUDPGet]))
+ .dequeued(rec.getSum(sDequeued[EVACGestureUDPGet]))
+ .resp_count(rec.getSum(sResponse[EVACGestureUDPGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACGestureUDPGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACGestureUDPGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACGestureUDPGet]).value());
}
- PerRegionStats & stats = *it->second;
-
- LLSD reg_stat = LLSD::emptyMap();
-
- for (int i = 0; i < LL_ARRAY_SIZE(tags); ++i)
+ if (!compact_output
+ || rec.getSum(sEnqueued[EVACOtherGet])
+ || rec.getSum(sDequeued[EVACOtherGet])
+ || rec.getSum(sResponse[EVACOtherGet]).value())
{
- PerRegionStats::prs_group & group(stats.mRequests[i]);
-
- if ((! compact_output) ||
- group.mEnqueued.getCount() ||
- group.mDequeued.getCount() ||
- group.mResponse.getCount())
- {
- LLSD & slot = reg_stat[tags[i]];
- slot = LLSD::emptyMap();
- slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount()));
- slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount()));
- slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount()));
- slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin() * 1.0e-6));
- slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax() * 1.0e-6));
- slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean() * 1.0e-6));
- }
+ r.get_other .enqueued(rec.getSum(sEnqueued[EVACOtherGet]))
+ .dequeued(rec.getSum(sDequeued[EVACOtherGet]))
+ .resp_count(rec.getSum(sResponse[EVACOtherGet]).value())
+ .resp_min(rec.getMin(sResponse[EVACOtherGet]).value())
+ .resp_max(rec.getMax(sResponse[EVACOtherGet]).value())
+ .resp_mean(rec.getMean(sResponse[EVACOtherGet]).value());
}
- if ((! compact_output) || stats.mFPS.getCount())
+ S32 fps = rec.getSum(LLStatViewer::FPS_SAMPLE);
+ if (!compact_output || fps != 0)
{
- LLSD & slot = reg_stat["fps"];
- slot = LLSD::emptyMap();
- slot[cnt_tag] = LLSD(S32(stats.mFPS.getCount()));
- slot[min_tag] = LLSD(F64(stats.mFPS.getMin()));
- slot[max_tag] = LLSD(F64(stats.mFPS.getMax()));
- slot[mean_tag] = LLSD(F64(stats.mFPS.getMean()));
+ r.fps.count(fps);
+ r.fps.min(rec.getMin(LLStatViewer::FPS_SAMPLE));
+ r.fps.max(rec.getMax(LLStatViewer::FPS_SAMPLE));
+ r.fps.mean(rec.getMean(LLStatViewer::FPS_SAMPLE));
}
U32 grid_x(0), grid_y(0);
grid_from_region_handle(it->first, &grid_x, &grid_y);
- reg_stat["grid_x"] = LLSD::Integer(grid_x);
- reg_stat["grid_y"] = LLSD::Integer(grid_y);
- reg_stat["duration"] = LLSD::Real(stats.mTotalTime * 1.0e-6);
- regions.append(reg_stat);
+ r.grid_x(grid_x);
+ r.grid_y(grid_y);
+ r.duration(LLUnit<LLUnits::Microseconds, F64>(rec.getDuration()).value());
}
- LLSD ret = LLSD::emptyMap();
- ret["regions"] = regions;
- ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6);
- LLSD avatar_info;
- avatar_info[avatar_nearby_tag] = LLSD::emptyArray();
+ stats.duration(mCurRecording ? LLUnit<LLUnits::Microseconds, F64>(mCurRecording->getDuration()).value() : 0.0);
+ stats.avatar.setProvided(true);
+
for (S32 rez_stat=0; rez_stat < mAvatarRezStates.size(); ++rez_stat)
{
- std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat);
- avatar_info[avatar_nearby_tag][rez_status_name] = mAvatarRezStates[rez_stat];
+ stats.avatar.nearby .cloud(mAvatarRezStates[0])
+ .gray(mAvatarRezStates[1])
+ .textured(mAvatarRezStates[2]);
}
- avatar_info[avatar_phase_stats_tag]["cloud"] = mPhaseStats["cloud"].getData();
- avatar_info[avatar_phase_stats_tag]["cloud-or-gray"] = mPhaseStats["cloud-or-gray"].getData();
- ret[avatar_tag] = avatar_info;
-
- return ret;
+
+ stats.avatar.phase_stats .cloud(mPhaseStats["cloud"].asLLSD())
+ .cloud_or_gray(mPhaseStats["cloud-or-gray"].asLLSD());
}
-void
-LLViewerAssetStats::merge(const LLViewerAssetStats & src)
+LLSD LLViewerAssetStats::asLLSD(bool compact_output)
{
- // mRegionHandle, mCurRegionStats and mResetTimestamp are left untouched.
- // Just merge the stats bodies
-
- const PerRegionContainer::const_iterator it_end(src.mRegionStats.end());
- for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it)
+ LLParamSDParser parser;
+ LLSD sd;
+ AssetStats stats;
+ getStats(stats, compact_output);
+ LLInitParam::predicate_rule_t rule = LLInitParam::default_parse_rules();
+ if (!compact_output)
{
- PerRegionContainer::iterator dst(mRegionStats.find(it->first));
- if (mRegionStats.end() == dst)
- {
- // Destination is missing data, just make a private copy
- mRegionStats[it->first] = new PerRegionStats(*it->second);
- }
- else
- {
- dst->second->merge(*it->second);
- }
+ rule.allow(LLInitParam::EMPTY);
}
+ parser.writeSD(sd, stats, rule);
+ return sd;
}
-
// ------------------------------------------------------
// Global free-function definitions (LLViewerAssetStatsFF namespace)
// ------------------------------------------------------
namespace LLViewerAssetStatsFF
{
-
-//
-// Target thread is elaborated in the function name. This could
-// have been something 'templatey' like specializations iterated
-// over a set of constants but with so few, this is clearer I think.
-//
-// As for the threads themselves... rather than do fine-grained
-// locking as we gather statistics, this code creates a collector
-// for each thread, allocated and run independently. Logging
-// happens at relatively infrequent intervals and at that time
-// the data is sent to a single thread to be aggregated into
-// a single entity with locks, thread safety and other niceties.
-//
-// A particularly fussy implementation would distribute the
-// per-thread pointers across separate cache lines. But that should
-// be beyond current requirements.
-//
-
-// 'main' thread - initial program thread
-
-void
-set_region_main(LLViewerAssetStats::region_handle_t region_handle)
-{
- if (! gViewerAssetStatsMain)
- return;
-
- gViewerAssetStatsMain->setRegion(region_handle);
-}
-
-void
-record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp)
-{
- if (! gViewerAssetStatsMain)
- return;
-
- gViewerAssetStatsMain->recordGetEnqueued(at, with_http, is_temp);
-}
-
-void
-record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp)
-{
- if (! gViewerAssetStatsMain)
- return;
-
- gViewerAssetStatsMain->recordGetDequeued(at, with_http, is_temp);
-}
-
-void
-record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
-{
- if (! gViewerAssetStatsMain)
- return;
-
- gViewerAssetStatsMain->recordGetServiced(at, with_http, is_temp, duration);
-}
-
-void
-record_fps_main(F32 fps)
+void set_region(LLViewerAssetStats::region_handle_t region_handle)
{
- if (! gViewerAssetStatsMain)
+ if (! gViewerAssetStats)
return;
- gViewerAssetStatsMain->recordFPS(fps);
+ gViewerAssetStats->setRegion(region_handle);
}
-void
-record_avatar_stats()
+void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
- if (! gViewerAssetStatsMain)
- return;
+ const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- gViewerAssetStatsMain->recordAvatarStats();
+ sEnqueued[int(eac)].add(1);
}
-// 'thread1' - should be for TextureFetch thread
-
-void
-set_region_thread1(LLViewerAssetStats::region_handle_t region_handle)
+void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
- if (! gViewerAssetStatsThread1)
- return;
+ const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- gViewerAssetStatsThread1->setRegion(region_handle);
+ sDequeued[int(eac)].add(1);
}
-void
-record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
{
- if (! gViewerAssetStatsThread1)
- return;
+ const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- gViewerAssetStatsThread1->recordGetEnqueued(at, with_http, is_temp);
+ sResponse[int(eac)].sample<LLTrace::Microseconds>(duration);
}
-void
-record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+void record_avatar_stats()
{
- if (! gViewerAssetStatsThread1)
+ if (! gViewerAssetStats)
return;
- gViewerAssetStatsThread1->recordGetDequeued(at, with_http, is_temp);
+ gViewerAssetStats->recordAvatarStats();
}
-void
-record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
+void init()
{
- if (! gViewerAssetStatsThread1)
- return;
-
- gViewerAssetStatsThread1->recordGetServiced(at, with_http, is_temp, duration);
-}
-
-
-void
-init()
-{
- if (! gViewerAssetStatsMain)
+ if (! gViewerAssetStats)
{
- gViewerAssetStatsMain = new LLViewerAssetStats();
- }
- if (! gViewerAssetStatsThread1)
- {
- gViewerAssetStatsThread1 = new LLViewerAssetStats();
+ gViewerAssetStats = new LLViewerAssetStats();
}
}
void
cleanup()
{
- delete gViewerAssetStatsMain;
- gViewerAssetStatsMain = 0;
-
- delete gViewerAssetStatsThread1;
- gViewerAssetStatsThread1 = 0;
+ delete gViewerAssetStats;
+ gViewerAssetStats = 0;
}
} // namespace LLViewerAssetStatsFF
-// ------------------------------------------------------
-// Local function definitions
-// ------------------------------------------------------
-namespace
+LLViewerAssetStats::AssetRequestType::AssetRequestType()
+: enqueued("enqueued"),
+ dequeued("dequeued"),
+ resp_count("resp_count"),
+ resp_min("resp_min"),
+ resp_max("resp_max"),
+ resp_mean("resp_mean")
+{}
+
+LLViewerAssetStats::FPSStats::FPSStats()
+: count("count"),
+ min("min"),
+ max("max"),
+ mean("mean")
+{}
+
+LLViewerAssetStats::RegionStats::RegionStats()
+: get_texture_temp_http("get_texture_temp_http"),
+ get_texture_temp_udp("get_texture_temp_udp"),
+ get_texture_non_temp_http("get_texture_non_temp_http"),
+ get_texture_non_temp_udp("get_texture_non_temp_udp"),
+ get_wearable_udp("get_wearable_udp"),
+ get_sound_udp("get_sound_udp"),
+ get_gesture_udp("get_gesture_udp"),
+ get_other("get_other"),
+ fps("fps"),
+ grid_x("grid_x"),
+ grid_y("grid_y"),
+ duration("duration")
+{}
+
+LLViewerAssetStats::AvatarRezState::AvatarRezState()
+: cloud("cloud"),
+ gray("gray"),
+ textured("textured")
+{}
+
+LLViewerAssetStats::AvatarInfo::AvatarInfo()
+: nearby("nearby"),
+ phase_stats("phase_stats")
{
-LLViewerAssetStats::EViewerAssetCategories
-asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp)
-{
- // For statistical purposes, we divide GETs into several
- // populations of asset fetches:
- // - textures which are de-prioritized in the asset system
- // - wearables (clothing, bodyparts) which directly affect
- // user experiences when they log in
- // - sounds
- // - gestures
- // - everything else.
- //
- llassert_always(50 == LLViewerAssetType::AT_COUNT);
-
- // Multiple asset definitions are floating around so this requires some
- // maintenance and attention.
- static const LLViewerAssetStats::EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] =
- {
- LLViewerAssetStats::EVACTextureTempHTTPGet, // (0) AT_TEXTURE
- LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND
- LLViewerAssetStats::EVACOtherGet, // AT_CALLINGCARD
- LLViewerAssetStats::EVACOtherGet, // AT_LANDMARK
- LLViewerAssetStats::EVACOtherGet, // AT_SCRIPT
- LLViewerAssetStats::EVACWearableUDPGet, // AT_CLOTHING
- LLViewerAssetStats::EVACOtherGet, // AT_OBJECT
- LLViewerAssetStats::EVACOtherGet, // AT_NOTECARD
- LLViewerAssetStats::EVACOtherGet, // AT_CATEGORY
- LLViewerAssetStats::EVACOtherGet, // AT_ROOT_CATEGORY
- LLViewerAssetStats::EVACOtherGet, // (10) AT_LSL_TEXT
- LLViewerAssetStats::EVACOtherGet, // AT_LSL_BYTECODE
- LLViewerAssetStats::EVACOtherGet, // AT_TEXTURE_TGA
- LLViewerAssetStats::EVACWearableUDPGet, // AT_BODYPART
- LLViewerAssetStats::EVACOtherGet, // AT_TRASH
- LLViewerAssetStats::EVACOtherGet, // AT_SNAPSHOT_CATEGORY
- LLViewerAssetStats::EVACOtherGet, // AT_LOST_AND_FOUND
- LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND_WAV
- LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_TGA
- LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_JPEG
- LLViewerAssetStats::EVACGestureUDPGet, // (20) AT_ANIMATION
- LLViewerAssetStats::EVACGestureUDPGet, // AT_GESTURE
- LLViewerAssetStats::EVACOtherGet, // AT_SIMSTATE
- LLViewerAssetStats::EVACOtherGet, // AT_FAVORITE
- LLViewerAssetStats::EVACOtherGet, // AT_LINK
- LLViewerAssetStats::EVACOtherGet, // AT_LINK_FOLDER
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, // (30)
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, // (40)
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, //
- LLViewerAssetStats::EVACOtherGet, // AT_MESH
- // (50)
- };
-
- if (at < 0 || at >= LLViewerAssetType::AT_COUNT)
- {
- return LLViewerAssetStats::EVACOtherGet;
- }
- LLViewerAssetStats::EViewerAssetCategories ret(asset_to_bin_map[at]);
- if (LLViewerAssetStats::EVACTextureTempHTTPGet == ret)
- {
- // Indexed with [is_temp][with_http]
- static const LLViewerAssetStats::EViewerAssetCategories texture_bin_map[2][2] =
- {
- {
- LLViewerAssetStats::EVACTextureNonTempUDPGet,
- LLViewerAssetStats::EVACTextureNonTempHTTPGet,
- },
- {
- LLViewerAssetStats::EVACTextureTempUDPGet,
- LLViewerAssetStats::EVACTextureTempHTTPGet,
- }
- };
-
- ret = texture_bin_map[is_temp][with_http];
- }
- return ret;
}
-} // anonymous namespace
+LLViewerAssetStats::AssetStats::AssetStats()
+: regions("regions"),
+ duration("duration"),
+ avatar("avatar"),
+ session_id("session_id"),
+ agent_id("agent_id"),
+ message("message"),
+ sequence("sequence"),
+ initial("initial"),
+ break_("break")
+{}