summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2010-11-10 08:44:53 -0800
committerMonty Brandenberg <monty@lindenlab.com>2010-11-10 08:44:53 -0800
commitfd2d4dc1b16430edd367a8b0f4162238bbb7e22c (patch)
treede1c5a1399ee7f1bedade0e2bb437f1816d968da /indra
parent1ed9d997a6c380f71f2da182c8083321e35b5034 (diff)
ESC-110 ESC-111
Cleanup passes on the two threaded collectors with better comments and more complete unit tests.
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llviewerassetstats.cpp172
-rw-r--r--indra/newview/llviewerassetstats.h152
-rw-r--r--indra/newview/tests/llviewerassetstats_test.cpp303
3 files changed, 533 insertions, 94 deletions
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index 0852573bbd..a6c4685bf1 100644
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -47,7 +47,7 @@
* <TBD>
*
* Unit Tests:
- * <TBD>
+ * indra/newview/tests/llviewerassetstats_test.cpp
*
*/
@@ -55,7 +55,8 @@
// ------------------------------------------------------
// Global data definitions
// ------------------------------------------------------
-LLViewerAssetStats * gViewerAssetStats = NULL;
+LLViewerAssetStats * gViewerAssetStatsMain(0);
+LLViewerAssetStats * gViewerAssetStatsThread1(0);
// ------------------------------------------------------
@@ -70,6 +71,21 @@ asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool i
}
// ------------------------------------------------------
+// LLViewerAssetStats::PerRegionStats struct definition
+// ------------------------------------------------------
+void
+LLViewerAssetStats::PerRegionStats::reset()
+{
+ for (int i(0); i < LL_ARRAY_SIZE(mRequests); ++i)
+ {
+ mRequests[i].mEnqueued.reset();
+ mRequests[i].mDequeued.reset();
+ mRequests[i].mResponse.reset();
+ }
+}
+
+
+// ------------------------------------------------------
// LLViewerAssetStats class definition
// ------------------------------------------------------
LLViewerAssetStats::LLViewerAssetStats()
@@ -81,20 +97,55 @@ LLViewerAssetStats::LLViewerAssetStats()
void
LLViewerAssetStats::reset()
{
- for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i)
+ // Empty the map of all region stats
+ mRegionStats.clear();
+
+ // If we have a current stats, reset it, otherwise, as at construction,
+ // create a new one.
+ if (mCurRegionStats)
{
- mRequests[i].mEnqueued.reset();
- mRequests[i].mDequeued.reset();
- mRequests[i].mResponse.reset();
+ mCurRegionStats->reset();
}
+ else
+ {
+ mCurRegionStats = new PerRegionStats(mRegionID);
+ }
+
+ // And add reference to map
+ mRegionStats[mRegionID] = mCurRegionStats;
}
+
+void
+LLViewerAssetStats::setRegionID(const LLUUID & region_id)
+{
+ if (region_id == mRegionID)
+ {
+ // Already active, ignore.
+ return;
+ }
+
+ PerRegionContainer::iterator new_stats = mRegionStats.find(region_id);
+ if (mRegionStats.end() == new_stats)
+ {
+ // Haven't seen this region_id before, create a new block make it current.
+ mCurRegionStats = new PerRegionStats(region_id);
+ mRegionStats[region_id] = mCurRegionStats;
+ }
+ else
+ {
+ mCurRegionStats = new_stats->second;
+ }
+ mRegionID = region_id;
+}
+
+
void
LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- ++mRequests[int(eac)].mEnqueued;
+ ++(mCurRegionStats->mRequests[int(eac)].mEnqueued);
}
void
@@ -102,7 +153,7 @@ LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at, bool with_htt
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- ++mRequests[int(eac)].mDequeued;
+ ++(mCurRegionStats->mRequests[int(eac)].mDequeued);
}
void
@@ -110,7 +161,7 @@ LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_htt
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- mRequests[int(eac)].mResponse.record(duration);
+ mCurRegionStats->mRequests[int(eac)].mResponse.record(duration);
}
const LLSD
@@ -139,16 +190,33 @@ LLViewerAssetStats::asLLSD() const
LLSD ret = LLSD::emptyMap();
- for (int i = 0; i < EVACCount; ++i)
+ for (PerRegionContainer::const_iterator it = mRegionStats.begin();
+ mRegionStats.end() != it;
+ ++it)
{
- LLSD & slot = ret[tags[i]];
- slot = LLSD::emptyMap();
- slot[enq_tag] = LLSD(S32(mRequests[i].mEnqueued.getCount()));
- slot[deq_tag] = LLSD(S32(mRequests[i].mDequeued.getCount()));
- slot[rcnt_tag] = LLSD(S32(mRequests[i].mResponse.getCount()));
- slot[rmin_tag] = LLSD(mRequests[i].mResponse.getMin());
- slot[rmax_tag] = LLSD(mRequests[i].mResponse.getMax());
- slot[rmean_tag] = LLSD(mRequests[i].mResponse.getMean());
+ if (it->first.isNull())
+ {
+ // Never emit NULL UUID in results.
+ continue;
+ }
+
+ const PerRegionStats & stats = *it->second;
+
+ LLSD reg_stat = LLSD::emptyMap();
+
+ for (int i = 0; i < EVACCount; ++i)
+ {
+ 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(stats.mRequests[i].mResponse.getMin());
+ slot[rmax_tag] = LLSD(stats.mRequests[i].mResponse.getMax());
+ slot[rmean_tag] = LLSD(stats.mRequests[i].mResponse.getMean());
+ }
+
+ ret[it->first.asString()] = reg_stat;
}
return ret;
@@ -161,31 +229,81 @@ LLViewerAssetStats::asLLSD() const
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.
+
+void
+set_region_main(const LLUUID & region_id)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ gViewerAssetStatsMain->setRegionID(region_id);
+}
+
+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, F64 duration)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ gViewerAssetStatsMain->recordGetServiced(at, with_http, is_temp, duration);
+}
+
+
+void
+set_region_thread1(const LLUUID & region_id)
+{
+ if (! gViewerAssetStatsThread1)
+ return;
+
+ gViewerAssetStatsThread1->setRegionID(region_id);
+}
+
void
-record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
- if (! gViewerAssetStats)
+ if (! gViewerAssetStatsThread1)
return;
- gViewerAssetStats->recordGetEnqueued(at, with_http, is_temp);
+ gViewerAssetStatsThread1->recordGetEnqueued(at, with_http, is_temp);
}
void
-record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
- if (! gViewerAssetStats)
+ if (! gViewerAssetStatsThread1)
return;
- gViewerAssetStats->recordGetDequeued(at, with_http, is_temp);
+ gViewerAssetStatsThread1->recordGetDequeued(at, with_http, is_temp);
}
void
-record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration)
+record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration)
{
- if (! gViewerAssetStats)
+ if (! gViewerAssetStatsThread1)
return;
- gViewerAssetStats->recordGetServiced(at, with_http, is_temp, duration);
+ gViewerAssetStatsThread1->recordGetServiced(at, with_http, is_temp, duration);
}
} // namespace LLViewerAssetStatsFF
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index 9d66a1e89b..b8356a5ff5 100644
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -36,6 +36,8 @@
#include "linden_common.h"
+#include "llpointer.h"
+#include "llrefcount.h"
#include "llviewerassettype.h"
#include "llviewerassetstorage.h"
#include "llsimplestat.h"
@@ -43,50 +45,42 @@
/**
* @class LLViewerAssetStats
- * @brief Records events and performance of asset put/get operations.
+ * @brief Records performance aspects of asset access operations.
*
- * The asset system is a combination of common code and server-
- * and viewer-overridden derivations. The common code is presented
- * in here as the 'front-end' and deriviations (really the server)
- * are presented as 'back-end'. The distinction isn't perfect as
- * there are legacy asset transfer systems which mostly appear
- * as front-end stats.
+ * This facility is derived from a very similar simulator-based
+ * one, LLSimAssetStats. It's function is to count asset access
+ * operations and characterize response times. Collected data
+ * are binned in several dimensions:
+ *
+ * - Asset types collapsed into a few aggregated categories
+ * - By simulator UUID
+ * - By transport mechanism (HTTP vs MessageSystem)
+ * - By persistence (temp vs non-temp)
+ *
+ * Statistics collected are fairly basic at this point:
*
- * Statistics collected are fairly basic:
* - Counts of enqueue and dequeue operations
- * - Counts of duplicated request fetches
* - Min/Max/Mean of asset transfer operations
*
- * While the stats collection interfaces appear to be fairly
- * orthogonal across methods (GET, PUT) and asset types (texture,
- * bodypart, etc.), the actual internal collection granularity
- * varies greatly. GET's operations found in the cache are
- * treated as a single group as are duplicate requests. Non-
- * cached items are broken down into three groups: textures,
- * wearables (bodyparts, clothing) and the rest. PUT operations
- * are broken down into two categories: temporary assets and
- * non-temp. Back-end operations do not distinguish asset types,
- * only GET, PUT (temp) and PUT (non-temp).
- *
- * No coverage for Estate Assets or Inventory Item Assets which use
- * some different interface conventions. It could be expanded to cover
- * them.
+ * This collector differs from the simulator-based on in a
+ * number of ways:
+ *
+ * - The front-end/back-end distinction doesn't exist in viewer
+ * code
+ * - Multiple threads must be safely accomodated in the viewer
*
* Access to results is by conversion to an LLSD with some standardized
- * key names. The intent of this structure is to be emitted as
+ * key names. The intent of this structure is that it be emitted as
* standard syslog-based metrics formatting where it can be picked
* up by interested parties.
*
- * For convenience, a set of free functions in namespace LLAssetStatsFF
- * are provided which operate on various counters in a way that
- * is highly-compatible with the simulator code.
+ * For convenience, a set of free functions in namespace
+ * LLViewerAssetStatsFF is provided for conditional test-and-call
+ * operations.
*/
class LLViewerAssetStats
{
public:
- LLViewerAssetStats();
- // Default destructor and assignment operator are correct.
-
enum EViewerAssetCategories
{
EVACTextureTempHTTPGet, //< Texture GETs
@@ -100,45 +94,109 @@ public:
EVACCount // Must be last
};
-
+
+ /**
+ * Collected data for a single region visited by the avatar.
+ */
+ class PerRegionStats : public LLRefCount
+ {
+ public:
+ PerRegionStats(const LLUUID & region_id)
+ : LLRefCount(),
+ mRegionID(region_id)
+ {
+ reset();
+ }
+
+ void reset();
+
+ public:
+ LLUUID mRegionID;
+ struct
+ {
+ LLSimpleStatCounter mEnqueued;
+ LLSimpleStatCounter mDequeued;
+ LLSimpleStatMMM<> mResponse;
+ } mRequests [EVACCount];
+ };
+
+public:
+ LLViewerAssetStats();
+ // Default destructor is correct.
+ LLViewerAssetStats & operator=(const LLViewerAssetStats &); // Not defined
+
+ // Clear all metrics data. This leaves the currently-active region
+ // in place but with zero'd data for all metrics. All other regions
+ // are removed from the collection map.
void reset();
+ // Set hidden region argument and establish context for subsequent
+ // collection calls.
+ void setRegionID(const LLUUID & region_id);
+
// Non-Cached GET Requests
void recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp);
void recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp);
void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration);
- // Report Generation
+ // Retrieve current metrics for all visited regions.
const LLSD asLLSD() const;
protected:
+ typedef std::map<LLUUID, LLPointer<PerRegionStats> > PerRegionContainer;
- struct
- {
- LLSimpleStatCounter mEnqueued;
- LLSimpleStatCounter mDequeued;
- LLSimpleStatMMM<> mResponse;
- } mRequests [EVACCount];
+ // Region of the currently-active region. Always valid but may
+ // be a NULL UUID after construction or when explicitly set. Unchanged
+ // by a reset() call.
+ LLUUID mRegionID;
+
+ // Pointer to metrics collection for currently-active region. Always
+ // valid and unchanged after reset() though contents will be changed.
+ // Always points to a collection contained in mRegionStats.
+ LLPointer<PerRegionStats> mCurRegionStats;
+
+ // Metrics data for all regions during one collection cycle
+ PerRegionContainer mRegionStats;
};
/**
- * Expectation is that the simulator and other asset-handling
- * code will create a single instance of the stats class and
- * make it available here. The free functions examine this
- * for non-zero and perform their functions conditionally. The
- * instance methods themselves make no assumption about this.
+ * Global stats collectors one for each independent thread where
+ * assets and other statistics are gathered. The globals are
+ * expected to be created at startup time and then picked up by
+ * their respective threads afterwards. A set of free functions
+ * are provided to access methods behind the globals while both
+ * minimally disrupting visual flow and supplying a description
+ * of intent.
+ *
+ * Expected thread assignments:
+ *
+ * - Main: main() program execution thread
+ * - Thread1: TextureFetch worker thread
*/
-extern LLViewerAssetStats * gViewerAssetStats;
+extern LLViewerAssetStats * gViewerAssetStatsMain;
+
+extern LLViewerAssetStats * gViewerAssetStatsThread1;
namespace LLViewerAssetStatsFF
{
-void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+void set_region_main(const LLUUID & region_id);
+
+void record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+
+void record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+
+void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration);
+
+
+void set_region_thread1(const LLUUID & region_id);
+
+void record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp);
-void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+void record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp);
-void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration);
+void record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration);
} // namespace LLViewerAssetStatsFF
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index 50d348c7e3..affe16c177 100644
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -38,6 +38,7 @@
#include "lltut.h"
#include "../llviewerassetstats.h"
+#include "lluuid.h"
static const char * all_keys[] =
{
@@ -73,6 +74,27 @@ static const char * sub_keys[] =
"resp_mean"
};
+static const LLUUID region1("4e2d81a3-6263-6ffe-ad5c-8ce04bee07e8");
+static const LLUUID region2("68762cc8-b68b-4e45-854b-e830734f2d4a");
+
+static bool
+is_empty_map(const LLSD & sd)
+{
+ return sd.isMap() && 0 == sd.size();
+}
+
+static bool
+is_single_key_map(const LLSD & sd, const std::string & key)
+{
+ return sd.isMap() && 1 == sd.size() && sd.has(key);
+}
+
+static bool
+is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2)
+{
+ return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2);
+}
+
namespace tut
{
struct tst_viewerassetstats_index
@@ -86,29 +108,40 @@ namespace tut
void tst_viewerassetstats_index_object_t::test<1>()
{
// Check that helpers aren't bothered by missing global stats
- ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats));
+ ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain));
- LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
- LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
- LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_GESTURE, false, false, 12.3);
+ LLViewerAssetStatsFF::record_response_main(LLViewerAssetType::AT_GESTURE, false, false, 12.3);
}
// Create a non-global instance and check the structure
template<> template<>
void tst_viewerassetstats_index_object_t::test<2>()
{
- ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats));
+ ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain));
LLViewerAssetStats * it = new LLViewerAssetStats();
- ensure("Global gViewerAssetStats should still be NULL", (NULL == gViewerAssetStats));
-
- LLSD sd = it->asLLSD();
-
- delete it;
+ ensure("Global gViewerAssetStatsMain should still be NULL", (NULL == gViewerAssetStatsMain));
+ LLSD sd_full = it->asLLSD();
+
+ // Default (NULL) region ID doesn't produce LLSD results so should
+ // get an empty map back from output
+ ensure("Null LLSD initially", is_empty_map(sd_full));
+
+ // Once the region is set, we will get a response even with no data collection
+ it->setRegionID(region1);
+ sd_full = it->asLLSD();
+ ensure("Correct single-key LLSD map", is_single_key_map(sd_full, region1.asString()));
+
+ LLSD sd = sd_full[region1.asString()];
+
+ delete it;
+
// Check the structure of the LLSD
for (int i = 0; i < LL_ARRAY_SIZE(all_keys); ++i)
{
@@ -131,8 +164,11 @@ namespace tut
void tst_viewerassetstats_index_object_t::test<3>()
{
LLViewerAssetStats * it = new LLViewerAssetStats();
+ it->setRegionID(region1);
LLSD sd = it->asLLSD();
+ ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString()));
+ sd = sd[region1.asString()];
delete it;
@@ -145,15 +181,57 @@ namespace tut
template<> template<>
void tst_viewerassetstats_index_object_t::test<4>()
{
- gViewerAssetStats = new LLViewerAssetStats();
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+ LLViewerAssetStatsFF::set_region_main(region1);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLSD sd = gViewerAssetStatsMain->asLLSD();
+ ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString()));
+ sd = sd[region1.asString()];
+
+ // Check a few points on the tree for content
+ ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_temp_udp][enqueued] is 0", (0 == sd["get_texture_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_non_temp_http][enqueued] is 0", (0 == sd["get_texture_non_temp_http"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_temp_http][enqueued] is 0", (0 == sd["get_texture_temp_http"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD()[region1.asString()];
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+
+ ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+ }
+
+ // Create two global instances and verify no interactions
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<5>()
+ {
+ gViewerAssetStatsThread1 = new LLViewerAssetStats();
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+ LLViewerAssetStatsFF::set_region_main(region1);
- LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false);
- LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
- LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false);
- LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
- LLSD sd = gViewerAssetStats->asLLSD();
+ LLSD sd = gViewerAssetStatsThread1->asLLSD();
+ ensure("Other collector is empty", is_empty_map(sd));
+ sd = gViewerAssetStatsMain->asLLSD();
+ ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString()));
+ sd = sd[region1.asString()];
// Check a few points on the tree for content
ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
@@ -163,11 +241,196 @@ namespace tut
ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
// Reset and check zeros...
- gViewerAssetStats->reset();
- sd = gViewerAssetStats->asLLSD();
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD()[region1.asString()];
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+ delete gViewerAssetStatsThread1;
+ gViewerAssetStatsThread1 = NULL;
+
+ ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+ }
+
+ // Check multiple region collection
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<6>()
+ {
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+
+ LLViewerAssetStatsFF::set_region_main(region1);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region2);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+
+ LLSD sd = gViewerAssetStatsMain->asLLSD();
+
+ ensure("Correct double-key LLSD map", is_double_key_map(sd, region1.asString(), region2.asString()));
+ LLSD sd1 = sd[region1.asString()];
+ LLSD sd2 = sd[region2.asString()];
+
+ // Check a few points on the tree for content
+ ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_temp_udp][enqueued] is 0", (0 == sd1["get_texture_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_non_temp_http][enqueued] is 0", (0 == sd1["get_texture_non_temp_http"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_temp_http][enqueued] is 0", (0 == sd1["get_texture_temp_http"]["enqueued"].asInteger()));
+ ensure("sd1[get_gesture_udp][dequeued] is 0", (0 == sd1["get_gesture_udp"]["dequeued"].asInteger()));
+
+ // Check a few points on the tree for content
+ ensure("sd2[get_gesture_udp][enqueued] is 4", (4 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
+ ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger()));
+ ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD();
+ ensure("Correct single-key LLSD map", is_single_key_map(sd, region2.asString()));
+ sd2 = sd[region2.asString()];
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+
+ ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
+ }
+
+ // Check multiple region collection jumping back-and-forth between regions
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<7>()
+ {
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+
+ LLViewerAssetStatsFF::set_region_main(region1);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region2);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region1);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, true, true);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, true, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region2);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+
+ LLSD sd = gViewerAssetStatsMain->asLLSD();
+
+ ensure("Correct double-key LLSD map", is_double_key_map(sd, region1.asString(), region2.asString()));
+ LLSD sd1 = sd[region1.asString()];
+ LLSD sd2 = sd[region2.asString()];
+
+ // Check a few points on the tree for content
+ ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_temp_udp][enqueued] is 0", (0 == sd1["get_texture_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_non_temp_http][enqueued] is 0", (0 == sd1["get_texture_non_temp_http"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_temp_http][enqueued] is 1", (1 == sd1["get_texture_temp_http"]["enqueued"].asInteger()));
+ ensure("sd1[get_gesture_udp][dequeued] is 0", (0 == sd1["get_gesture_udp"]["dequeued"].asInteger()));
+
+ // Check a few points on the tree for content
+ ensure("sd2[get_gesture_udp][enqueued] is 8", (8 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
+ ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger()));
+ ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD();
+ ensure("Correct single-key LLSD map", is_single_key_map(sd, region2.asString()));
+ sd2 = sd[region2.asString()];
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+
+ ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
+ }
+
+ // Non-texture assets ignore transport and persistence flags
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<8>()
+ {
+ gViewerAssetStatsThread1 = new LLViewerAssetStats();
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+ LLViewerAssetStatsFF::set_region_main(region1);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, true);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, true);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ LLSD sd = gViewerAssetStatsThread1->asLLSD();
+ ensure("Other collector is empty", is_empty_map(sd));
+ sd = gViewerAssetStatsMain->asLLSD();
+ ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString()));
+ sd = sd[region1.asString()];
+
+ // Check a few points on the tree for content
+ ensure("sd[get_gesture_udp][enqueued] is 0", (0 == sd["get_gesture_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+
+ ensure("sd[get_wearable_udp][enqueued] is 4", (4 == sd["get_wearable_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_wearable_udp][dequeued] is 4", (4 == sd["get_wearable_udp"]["dequeued"].asInteger()));
+
+ ensure("sd[get_other][enqueued] is 4", (4 == sd["get_other"]["enqueued"].asInteger()));
+ ensure("sd[get_other][dequeued] is 0", (0 == sd["get_other"]["dequeued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD()[region1.asString()];
- delete gViewerAssetStats;
- gViewerAssetStats = NULL;
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+ delete gViewerAssetStatsThread1;
+ gViewerAssetStatsThread1 = NULL;
ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));