Massive sunshine/viewer-dev catchup. Further implemented serverside baking and added/updated metrics feedback.
This commit is contained in:
611
indra/newview/llviewerassetstats.cpp
Normal file
611
indra/newview/llviewerassetstats.cpp
Normal file
@@ -0,0 +1,611 @@
|
||||
/**
|
||||
* @file llviewerassetstats.cpp
|
||||
* @brief
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llviewerassetstats.h"
|
||||
#include "llregionhandle.h"
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
/*
|
||||
* Classes and utility functions for per-thread and per-region
|
||||
* asset and experiential metrics to be aggregated grid-wide.
|
||||
*
|
||||
* The basic metrics grouping is LLViewerAssetStats::PerRegionStats.
|
||||
* This provides various counters and simple statistics for asset
|
||||
* fetches binned into a few categories. One of these is maintained
|
||||
* for each region encountered and the 'current' region is available
|
||||
* as a simple reference. Each thread (presently two) interested
|
||||
* in participating in these stats gets an instance of the
|
||||
* LLViewerAssetStats class so that threads are completely
|
||||
* independent.
|
||||
*
|
||||
* The idea of a current region is used for simplicity and speed
|
||||
* of categorization. Each metrics event could have taken a
|
||||
* region uuid argument resulting in a suitable lookup. Arguments
|
||||
* against this design include:
|
||||
*
|
||||
* - Region uuid not trivially available to caller.
|
||||
* - Cost (cpu, disruption in real work flow) too high.
|
||||
* - Additional precision not really meaningful.
|
||||
*
|
||||
* By itself, the LLViewerAssetStats class is thread- and
|
||||
* viewer-agnostic and can be used anywhere without assumptions
|
||||
* of global pointers and other context. For the viewer,
|
||||
* a set of free functions are provided in the namespace
|
||||
* LLViewerAssetStatsFF which *do* implement viewer-native
|
||||
* policies about per-thread globals and will do correct
|
||||
* defensive tests of same.
|
||||
*
|
||||
* References
|
||||
*
|
||||
* Project:
|
||||
* <TBD>
|
||||
*
|
||||
* Test Plan:
|
||||
* <TBD>
|
||||
*
|
||||
* Jiras:
|
||||
* <TBD>
|
||||
*
|
||||
* Unit Tests:
|
||||
* indra/newview/tests/llviewerassetstats_test.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Global data definitions
|
||||
// ------------------------------------------------------
|
||||
LLViewerAssetStats * gViewerAssetStatsMain(0);
|
||||
LLViewerAssetStats * gViewerAssetStatsThread1(0);
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Local declarations
|
||||
// ------------------------------------------------------
|
||||
namespace
|
||||
{
|
||||
|
||||
static LLViewerAssetStats::EViewerAssetCategories
|
||||
asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp);
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
// 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();
|
||||
}
|
||||
mFPS.reset();
|
||||
|
||||
mTotalTime = 0;
|
||||
mStartTimestamp = LLViewerAssetStatsFF::get_timestamp();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionStats & src)
|
||||
{
|
||||
// mRegionHandle, mTotalTime, mStartTimestamp are left alone.
|
||||
|
||||
// mFPS
|
||||
if (src.mFPS.getCount() && mFPS.getCount())
|
||||
{
|
||||
mFPS.merge(src.mFPS);
|
||||
}
|
||||
|
||||
// Requests
|
||||
for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i)
|
||||
{
|
||||
mRequests[i].mEnqueued.merge(src.mRequests[i].mEnqueued);
|
||||
mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued);
|
||||
mRequests[i].mResponse.merge(src.mRequests[i].mResponse);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LLViewerAssetStats::PerRegionStats::accumulateTime(duration_t now)
|
||||
{
|
||||
mTotalTime += (now - mStartTimestamp);
|
||||
mStartTimestamp = now;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// LLViewerAssetStats class definition
|
||||
// ------------------------------------------------------
|
||||
LLViewerAssetStats::LLViewerAssetStats()
|
||||
: mRegionHandle(U64(0))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src)
|
||||
: mRegionHandle(src.mRegionHandle),
|
||||
mResetTimestamp(src.mResetTimestamp)
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LLViewerAssetStats::reset()
|
||||
{
|
||||
// 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 as we must always have a current stats block.
|
||||
if (mCurRegionStats)
|
||||
{
|
||||
mCurRegionStats->reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurRegionStats = new PerRegionStats(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)
|
||||
{
|
||||
if (region_handle == mRegionHandle)
|
||||
{
|
||||
// Already active, ignore.
|
||||
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)
|
||||
{
|
||||
// Haven't seen this region_id before, create a new block and make it current.
|
||||
mCurRegionStats = new PerRegionStats(region_handle);
|
||||
mRegionStats[region_handle] = mCurRegionStats;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurRegionStats = new_stats->second;
|
||||
}
|
||||
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)
|
||||
{
|
||||
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
|
||||
|
||||
++(mCurRegionStats->mRequests[int(eac)].mDequeued);
|
||||
}
|
||||
|
||||
void
|
||||
LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration)
|
||||
{
|
||||
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
|
||||
|
||||
mCurRegionStats->mRequests[int(eac)].mResponse.record(duration);
|
||||
}
|
||||
|
||||
void
|
||||
LLViewerAssetStats::recordFPS(F32 fps)
|
||||
{
|
||||
mCurRegionStats->mFPS.record(fps);
|
||||
}
|
||||
|
||||
LLSD
|
||||
LLViewerAssetStats::asLLSD(bool compact_output)
|
||||
{
|
||||
// Top-level tags
|
||||
static const LLSD::String tags[EVACCount] =
|
||||
{
|
||||
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")
|
||||
};
|
||||
|
||||
// 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");
|
||||
|
||||
const duration_t now = LLViewerAssetStatsFF::get_timestamp();
|
||||
mCurRegionStats->accumulateTime(now);
|
||||
|
||||
LLSD regions = LLSD::emptyArray();
|
||||
for (PerRegionContainer::iterator it = mRegionStats.begin();
|
||||
mRegionStats.end() != it;
|
||||
++it)
|
||||
{
|
||||
if (0 == it->first)
|
||||
{
|
||||
// Never emit NULL UUID/handle in results.
|
||||
continue;
|
||||
}
|
||||
|
||||
PerRegionStats & stats = *it->second;
|
||||
|
||||
LLSD reg_stat = LLSD::emptyMap();
|
||||
|
||||
for (int i = 0; i < LL_ARRAY_SIZE(tags); ++i)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
if ((! compact_output) || stats.mFPS.getCount())
|
||||
{
|
||||
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()));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
LLSD ret = LLSD::emptyMap();
|
||||
ret["regions"] = regions;
|
||||
ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
LLViewerAssetStats::merge(const LLViewerAssetStats & src)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// 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)
|
||||
{
|
||||
if (! gViewerAssetStatsMain)
|
||||
return;
|
||||
|
||||
gViewerAssetStatsMain->recordFPS(fps);
|
||||
}
|
||||
|
||||
// 'thread1' - should be for TextureFetch thread
|
||||
|
||||
void
|
||||
set_region_thread1(LLViewerAssetStats::region_handle_t region_handle)
|
||||
{
|
||||
if (! gViewerAssetStatsThread1)
|
||||
return;
|
||||
|
||||
gViewerAssetStatsThread1->setRegion(region_handle);
|
||||
}
|
||||
|
||||
void
|
||||
record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
|
||||
{
|
||||
if (! gViewerAssetStatsThread1)
|
||||
return;
|
||||
|
||||
gViewerAssetStatsThread1->recordGetEnqueued(at, with_http, is_temp);
|
||||
}
|
||||
|
||||
void
|
||||
record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
|
||||
{
|
||||
if (! gViewerAssetStatsThread1)
|
||||
return;
|
||||
|
||||
gViewerAssetStatsThread1->recordGetDequeued(at, with_http, is_temp);
|
||||
}
|
||||
|
||||
void
|
||||
record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
|
||||
{
|
||||
if (! gViewerAssetStatsThread1)
|
||||
return;
|
||||
|
||||
gViewerAssetStatsThread1->recordGetServiced(at, with_http, is_temp, duration);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
init()
|
||||
{
|
||||
if (! gViewerAssetStatsMain)
|
||||
{
|
||||
gViewerAssetStatsMain = new LLViewerAssetStats();
|
||||
}
|
||||
if (! gViewerAssetStatsThread1)
|
||||
{
|
||||
gViewerAssetStatsThread1 = new LLViewerAssetStats();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cleanup()
|
||||
{
|
||||
delete gViewerAssetStatsMain;
|
||||
gViewerAssetStatsMain = 0;
|
||||
|
||||
delete gViewerAssetStatsThread1;
|
||||
gViewerAssetStatsThread1 = 0;
|
||||
}
|
||||
|
||||
|
||||
} // namespace LLViewerAssetStatsFF
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Local function definitions
|
||||
// ------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user