diff options
-rwxr-xr-x | indra/llcommon/llfasttimer.cpp | 9 | ||||
-rwxr-xr-x | indra/llcommon/llfasttimer.h | 2 | ||||
-rwxr-xr-x | indra/llcommon/llinstancetracker.h | 27 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 5 | ||||
-rw-r--r-- | indra/llcommon/lltraceaccumulators.h | 15 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 29 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 35 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 2 | ||||
-rwxr-xr-x | indra/newview/llviewerstats.cpp | 10 |
9 files changed, 110 insertions, 24 deletions
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 2db44adacf..d97fa74c24 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -131,10 +131,10 @@ struct SortTimerByName } }; +static BlockTimerStatHandle sRootTimer("root", NULL); BlockTimerStatHandle& BlockTimerStatHandle::getRootTimeBlock() { - static BlockTimerStatHandle root_timer("root", NULL); - return root_timer; + return sRootTimer; } void BlockTimerStatHandle::pushLog(LLSD log) @@ -333,6 +333,11 @@ std::vector<BlockTimerStatHandle*>& BlockTimerStatHandle::getChildren() return getTreeNode().mChildren; } +bool BlockTimerStatHandle::hasChildren() +{ + return ! getTreeNode().mChildren.empty(); +} + // static void BlockTimerStatHandle::logStats() { diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 4821d6c386..614e7fdb4c 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -88,7 +88,6 @@ class BlockTimerStatHandle : public StatType<TimeBlockAccumulator> { public: - typedef LLInstanceTracker<StatType<TimeBlockAccumulator>, std::string> instance_tracker_t; BlockTimerStatHandle(const char* name, const char* description = ""); TimeBlockTreeNode& getTreeNode() const; @@ -99,6 +98,7 @@ public: typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter; child_iter beginChildren(); child_iter endChildren(); + bool hasChildren(); std::vector<BlockTimerStatHandle*>& getChildren(); StatType<TimeBlockAccumulator::CallCountFacet>& callCount() diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index f2b982c4c3..3fdb84cfd7 100755 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -62,16 +62,22 @@ protected: LL_COMMON_API void assert_main_thread(); +enum EInstanceTrackerAllowKeyCollisions +{ + InstanceTrackerAllowKeyCollisions, + InstanceTrackerDisallowKeyCollisions +}; + /// This mix-in class adds support for tracking all instances of the specified class parameter T /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set /// @NOTE: see explicit specialization below for default KEY==void case /// @NOTE: this class is not thread-safe unless used as read-only -template<typename T, typename KEY = void> +template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS = InstanceTrackerDisallowKeyCollisions> class LLInstanceTracker : public LLInstanceTrackerBase { typedef LLInstanceTracker<T, KEY> self_t; - typedef typename std::map<KEY, T*> InstanceMap; + typedef typename std::multimap<KEY, T*> InstanceMap; struct StaticData: public StaticBase { InstanceMap sMap; @@ -208,7 +214,18 @@ private: void add_(KEY key) { mInstanceKey = key; - getMap_()[key] = static_cast<T*>(this); + InstanceMap& map = getMap_(); + typename InstanceMap::iterator insertion_point_it = map.lower_bound(key); + if (ALLOW_KEY_COLLISIONS == InstanceTrackerDisallowKeyCollisions + && insertion_point_it != map.end() + && insertion_point_it->first == key) + { + LL_ERRS() << "Key " << key << " already exists in instance map for " << typeid(T).name() << LL_ENDL; + } + else + { + map.insert(insertion_point_it, std::make_pair(key, static_cast<T*>(this))); + } } void remove_() { @@ -225,8 +242,8 @@ private: /// explicit specialization for default case where KEY is void /// use a simple std::set<T*> -template<typename T> -class LLInstanceTracker<T, void> : public LLInstanceTrackerBase +template<typename T, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS> +class LLInstanceTracker<T, void, ALLOW_KEY_COLLISIONS> : public LLInstanceTrackerBase { typedef LLInstanceTracker<T, void> self_t; typedef typename std::set<T*> InstanceSet; diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index cbdf4e4a6f..b499036af2 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -69,11 +69,12 @@ protected: template<typename ACCUMULATOR> class StatType : public StatBase, - public LLInstanceTracker<StatType<ACCUMULATOR>, std::string> + public LLInstanceTracker<StatType<ACCUMULATOR>, std::string, InstanceTrackerAllowKeyCollisions> { public: + typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string, InstanceTrackerAllowKeyCollisions> instance_tracker_t; StatType(const char* name, const char* description) - : LLInstanceTracker<StatType<ACCUMULATOR>, std::string>(name), + : instance_tracker_t(name), StatBase(name, description), mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot()) {} diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index c30cc9a107..2971907849 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -226,6 +226,7 @@ namespace LLTrace { public: typedef F64 value_t; + static F64 getDefaultValue() { return NaN; } EventAccumulator() : mSum(0), @@ -293,6 +294,7 @@ namespace LLTrace { public: typedef F64 value_t; + static F64 getDefaultValue() { return NaN; } SampleAccumulator() : mSum(0), @@ -385,6 +387,7 @@ namespace LLTrace { public: typedef F64 value_t; + static F64 getDefaultValue() { return 0; } CountAccumulator() : mSum(0), @@ -415,6 +418,8 @@ namespace LLTrace S32 getSampleCount() const { return mNumSamples; } + bool hasValue() const { return true; } + private: F64 mSum; @@ -425,6 +430,8 @@ namespace LLTrace { public: typedef F64Seconds value_t; + static F64Seconds getDefaultValue() { return F64Seconds(0); } + typedef TimeBlockAccumulator self_t; // fake classes that allows us to view different facets of underlying statistic @@ -453,6 +460,7 @@ namespace LLTrace void addSamples(const self_t& other, EBufferAppendType append_type); void reset(const self_t* other); void sync(F64SecondsImplicit) {} + bool hasValue() const { return true; } // // members @@ -493,17 +501,22 @@ namespace LLTrace struct MemAccumulator { + typedef F64Bytes value_t; + static F64Bytes getDefaultValue() { return F64Bytes(0); } + typedef MemAccumulator self_t; // fake classes that allows us to view different facets of underlying statistic struct AllocationFacet { typedef F64Bytes value_t; + static F64Bytes getDefaultValue() { return F64Bytes(0); } }; struct DeallocationFacet { typedef F64Bytes value_t; + static F64Bytes getDefaultValue() { return F64Bytes(0); } }; void addSamples(const MemAccumulator& other, EBufferAppendType append_type) @@ -536,6 +549,8 @@ namespace LLTrace mSize.sync(time_stamp); } + bool hasValue() const { return mSize.hasValue(); } + SampleAccumulator mSize; EventAccumulator mAllocations; CountAccumulator mDeallocations; diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 2b2b55f614..6ad6bbe356 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -137,6 +137,12 @@ void Recording::appendRecording( Recording& other ) mElapsedSeconds += other.mElapsedSeconds; } +bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat) +{ + llassert(!isStarted()); + return mBuffers->mStackTimers[stat.getIndex()].hasValue(); +} + F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat) { llassert(!isStarted()); @@ -219,6 +225,12 @@ F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat) return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue()); } +bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat) +{ + llassert(!isStarted()); + return mBuffers->mMemStats[stat.getIndex()].mAllocations.hasValue(); +} + F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat) { llassert(!isStarted()); @@ -237,6 +249,13 @@ S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& s return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount(); } +bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat) +{ + llassert(!isStarted()); + return mBuffers->mMemStats[stat.getIndex()].mDeallocations.hasValue(); +} + + F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat) { llassert(!isStarted()); @@ -255,13 +274,19 @@ S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount(); } -F64 Recording::getSum( const StatType<CountAccumulator>& stat ) +bool Recording::hasValue(const StatType<CountAccumulator>& stat) +{ + llassert(!isStarted()); + return mBuffers->mCounts[stat.getIndex()].hasValue(); +} + +F64 Recording::getSum(const StatType<CountAccumulator>& stat) { llassert(!isStarted()); return mBuffers->mCounts[stat.getIndex()].getSum(); } -F64 Recording::getSum( const StatType<EventAccumulator>& stat ) +F64 Recording::getSum( const StatType<EventAccumulator>& stat) { llassert(!isStarted()); return (F64)mBuffers->mEvents[stat.getIndex()].getSum(); diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 810f796666..4b7a5ef0da 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -168,6 +168,7 @@ namespace LLTrace void makeUnique() { mBuffers.makeUnique(); } // Timer accessors + bool hasValue(const StatType<TimeBlockAccumulator>& stat); F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat); F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); @@ -178,22 +179,24 @@ namespace LLTrace // Memory accessors bool hasValue(const StatType<MemAccumulator>& stat); - F64Kilobytes getMin(const StatType<MemAccumulator>& stat); F64Kilobytes getMean(const StatType<MemAccumulator>& stat); F64Kilobytes getMax(const StatType<MemAccumulator>& stat); F64Kilobytes getStandardDeviation(const StatType<MemAccumulator>& stat); F64Kilobytes getLastValue(const StatType<MemAccumulator>& stat); + bool hasValue(const StatType<MemAccumulator::AllocationFacet>& stat); F64Kilobytes getSum(const StatType<MemAccumulator::AllocationFacet>& stat); F64Kilobytes getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat); S32 getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat); + bool hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat); F64Kilobytes getSum(const StatType<MemAccumulator::DeallocationFacet>& stat); F64Kilobytes getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat); S32 getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat); // CountStatHandle accessors + bool hasValue(const StatType<CountAccumulator>& stat); F64 getSum(const StatType<CountAccumulator>& stat); template <typename T> typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat) @@ -367,13 +370,21 @@ namespace LLTrace S32 total_periods = mNumPeriods; num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max(); + bool has_value = false; + T::value_t min_val(std::numeric_limits<T::value_t>::max()); for (S32 i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); - min_val = llmin(min_val, recording.getSum(stat)); + if (recording.hasValue(stat)) + { + min_val = llmin(min_val, recording.getSum(stat)); + has_value = true; + } } - return min_val; + + return has_value + ? min_val + : T::getDefaultValue(); } template<typename T> @@ -405,7 +416,7 @@ namespace LLTrace S32 total_periods = mNumPeriods; num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - typename RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max(); + typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max()); for (S32 i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); @@ -431,13 +442,21 @@ namespace LLTrace S32 total_periods = mNumPeriods; num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - typename T::value_t max_val = std::numeric_limits<typename T::value_t>::min(); + bool has_value = false; + T::value_t max_val(std::numeric_limits<T::value_t>::min()); for (S32 i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); - max_val = llmax(max_val, recording.getSum(stat)); + if (recording.hasValue(stat)) + { + max_val = llmax(max_val, recording.getSum(stat)); + has_value = true; + } } - return max_val; + + return has_value + ? max_val + : T::getDefaultValue(); } template<typename T> diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 20e8a0bbaa..7b7da5343d 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -81,7 +81,7 @@ void ThreadRecorder::init() BlockTimerStatHandle::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1; claim_alloc(gTraceMemStat, this); - claim_alloc(gTraceMemStat, sizeof(BlockTimer)); + claim_alloc(gTraceMemStat, mRootTimer); claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); } diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index c81a9a0ad3..d5ae2d1030 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -208,7 +208,7 @@ LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT_RATE(" LLViewerStats::LLViewerStats() : mLastTimeDiff(0.0) { - mRecording.start(); + getRecording().start(); } LLViewerStats::~LLViewerStats() @@ -216,7 +216,7 @@ LLViewerStats::~LLViewerStats() void LLViewerStats::resetStats() { - LLViewerStats::instance().mRecording.reset(); + getRecording().reset(); } void LLViewerStats::updateFrameStats(const F64Seconds time_diff) @@ -343,7 +343,7 @@ void update_statistics() sample(LLStatViewer::DRAW_DISTANCE, (F64)gSavedSettings.getF32("RenderFarClip")); sample(LLStatViewer::CHAT_BUBBLES, gSavedSettings.getBOOL("UseChatBubbles")); - typedef LLInstanceTracker<LLTrace::StatType<LLTrace::TimeBlockAccumulator>, std::string> stat_type_t; + typedef LLTrace::StatType<LLTrace::TimeBlockAccumulator>::instance_tracker_t stat_type_t; F64Seconds idle_secs = last_frame_recording.getSum(*stat_type_t::getInstance("Idle")); F64Seconds network_secs = last_frame_recording.getSum(*stat_type_t::getInstance("Network")); @@ -457,6 +457,8 @@ void send_stats() return; } + LLViewerStats::instance().getRecording().pause(); + body["session_id"] = gAgentSessionID; LLSD &agent = body["agent"]; @@ -616,6 +618,8 @@ void send_stats() LLViewerStats::getInstance()->addToMessage(body); LLHTTPClient::post(url, body, new ViewerStatsResponder()); + + LLViewerStats::instance().getRecording().resume(); } LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name) |