diff options
Diffstat (limited to 'indra/llcommon/llstat.h')
-rw-r--r-- | indra/llcommon/llstat.h | 236 |
1 files changed, 192 insertions, 44 deletions
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index e20c01f67f..b877432e86 100644 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -2,30 +2,25 @@ * @file llstat.h * @brief Runtime statistics accumulation. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,9 +28,16 @@ #define LL_LLSTAT_H #include <deque> +#include <map> #include "lltimer.h" #include "llframetimer.h" +#include "llfile.h" + +class LLSD; + +// Set this if longer stats are needed +#define ENABLE_LONG_TIME_STATS 0 // // Accumulates statistics for an arbitrary length of time. @@ -44,7 +46,7 @@ // amounts of time with very low memory cost. // -class LLStatAccum +class LL_COMMON_API LLStatAccum { protected: LLStatAccum(bool use_frame_timer); @@ -52,28 +54,63 @@ protected: public: enum TimeScale { + SCALE_100MS, SCALE_SECOND, SCALE_MINUTE, - SCALE_TWO_MINUTE, +#if ENABLE_LONG_TIME_STATS SCALE_HOUR, SCALE_DAY, SCALE_WEEK, - - NUM_SCALES +#endif + NUM_SCALES, // Use to size storage arrays + SCALE_PER_FRAME // For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets }; - F32 meanValue(TimeScale scale) const; + static U64 sScaleTimes[NUM_SCALES]; + + virtual F32 meanValue(TimeScale scale) const; // see the subclasses for the specific meaning of value + F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); } F32 meanValueOverLastSecond() const { return meanValue(SCALE_SECOND); } F32 meanValueOverLastMinute() const { return meanValue(SCALE_MINUTE); } -protected: - class impl; - impl& m; + void reset(U64 when); + + void sum(F64 value); + void sum(F64 value, U64 when); + + U64 getCurrentUsecs() const; + // Get current microseconds based on timer type + + BOOL mUseFrameTimer; + BOOL mRunning; + + U64 mLastTime; + + struct Bucket + { + Bucket() : + accum(0.0), + endTime(0), + lastValid(false), + lastAccum(0.0) + {} + + F64 accum; + U64 endTime; + + bool lastValid; + F64 lastAccum; + }; + + Bucket mBuckets[NUM_SCALES]; + + BOOL mLastSampleValid; + F64 mLastSampleValue; }; -class LLStatMeasure : public LLStatAccum +class LL_COMMON_API LLStatMeasure : public LLStatAccum // gathers statistics about things that are measured // ex.: tempature, time dilation { @@ -88,7 +125,7 @@ public: }; -class LLStatRate : public LLStatAccum +class LL_COMMON_API LLStatRate : public LLStatAccum // gathers statistics about things that can be counted over time // ex.: LSL instructions executed, messages sent, simulator frames completed // renders it in terms of rate of thing per second @@ -99,43 +136,140 @@ public: void count(U32); // used to note that n items have occured - void mark() { count(1); } + void mark(); // used for counting the rate thorugh a point in the code }; -class LLTimeBlock; - -class LLStatTime : public LLStatAccum +class LL_COMMON_API LLStatTime : public LLStatAccum // gathers statistics about time spent in a block of code // measure average duration per second in the block { public: - LLStatTime(bool use_frame_timer = false); + LLStatTime( const std::string & key = "undefined" ); + + U32 mFrameNumber; // Current frame number + U64 mTotalTimeInFrame; // Total time (microseconds) accumulated during the last frame + + void setKey( const std::string & key ) { mKey = key; }; + + virtual F32 meanValue(TimeScale scale) const; private: - void start(); + void start(); // Start and stop measuring time block void stop(); - friend class LLTimeBlock; + + std::string mKey; // Tag representing this time block + +#if LL_DEBUG + BOOL mRunning; // TRUE if start() has been called +#endif + + friend class LLPerfBlock; }; -class LLTimeBlock +// ---------------------------------------------------------------------------- + + +// Use this class on the stack to record statistics about an area of code +class LL_COMMON_API LLPerfBlock { public: - LLTimeBlock(LLStatTime& stat) : mStat(stat) { mStat.start(); } - ~LLTimeBlock() { mStat.stop(); } + struct StatEntry + { + StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {} + LLStatTime mStat; + U32 mCount; + }; + typedef std::map<std::string, StatEntry*> stat_map_t; + + // Use this constructor for pre-defined LLStatTime objects + LLPerfBlock(LLStatTime* stat); + + // Use this constructor for normal, optional LLPerfBlock time slices + LLPerfBlock( const char* key ); + + // Use this constructor for dynamically created LLPerfBlock time slices + // that are only enabled by specific control flags + LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS ); + + ~LLPerfBlock(); + + enum + { // Stats bitfield flags + LLSTATS_NO_OPTIONAL_STATS = 0x00, // No optional stats gathering, just pre-defined LLStatTime objects + LLSTATS_BASIC_STATS = 0x01, // Gather basic optional runtime stats + LLSTATS_SCRIPT_FUNCTIONS = 0x02, // Include LSL function calls + }; + static void setStatsFlags( S32 flags ) { sStatsFlags = flags; }; + static S32 getStatsFlags() { return sStatsFlags; }; + + static void clearDynamicStats(); // Reset maps to clear out dynamic objects + static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin + LLStatAccum::TimeScale scale ); + private: - LLStatTime& mStat; + // Initialize dynamically created LLStatTime objects + void initDynamicStat(const std::string& key); + + std::string mLastPath; // Save sCurrentStatPath when this is called + LLStatTime * mPredefinedStat; // LLStatTime object to get data + StatEntry * mDynamicStat; // StatEntryobject to get data + + static S32 sStatsFlags; // Control what is being recorded + static stat_map_t sStatMap; // Map full path string to LLStatTime objects + static std::string sCurrentStatPath; // Something like "frame/physics/physics step" }; +// ---------------------------------------------------------------------------- +class LL_COMMON_API LLPerfStats +{ +public: + LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0); + virtual ~LLPerfStats(); + + virtual void init(); // Reset and start all stat timers + virtual void updatePerFrameStats(); + // Override these function to add process-specific information to the performance log header and per-frame logging. + virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ } + virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ } + + // High-resolution frame stats + BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); }; + F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; }; + void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; }; + void setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS ); + void setProcessName(const std::string& process_name) { mProcessName = process_name; } + void setProcessPID(S32 process_pid) { mProcessPID = process_pid; } + +protected: + void openPerfStatsFile(); // Open file for high resolution metrics logging + void dumpIntervalPerformanceStats(); + llofstream mFrameStatsFile; // File for per-frame stats + BOOL mFrameStatsFileFailure; // Flag to prevent repeat opening attempts + BOOL mSkipFirstFrameStats; // Flag to skip one (partial) frame report + std::string mProcessName; + S32 mProcessPID; +private: + F32 mReportPerformanceStatInterval; // Seconds between performance stats + F64 mReportPerformanceStatEnd; // End time (seconds) for performance stats +}; -class LLStat +// ---------------------------------------------------------------------------- +class LL_COMMON_API LLStat { +private: + typedef std::multimap<std::string, LLStat*> stat_map_t; + static stat_map_t sStatList; + + void init(); + public: - LLStat(const U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE); ~LLStat(); void reset(); @@ -198,8 +332,22 @@ private: F32 *mDT; S32 mCurBin; S32 mNextBin; + + std::string mName; + static LLTimer sTimer; static LLFrameTimer sFrameTimer; + +public: + static LLStat* getStat(const std::string& name) + { + // return the first stat that matches 'name' + stat_map_t::iterator iter = sStatList.find(name); + if (iter != sStatList.end()) + return iter->second; + else + return NULL; + } }; - + #endif // LL_STAT_ |