PageRenderTime 117ms CodeModel.GetById 94ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llstat.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 353 lines | 222 code | 75 blank | 56 comment | 2 complexity | 3fa383114be0261e500615aa102439eb MD5 | raw file
  1/** 
  2 * @file llstat.h
  3 * @brief Runtime statistics accumulation.
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_LLSTAT_H
 28#define LL_LLSTAT_H
 29
 30#include <deque>
 31#include <map>
 32
 33#include "lltimer.h"
 34#include "llframetimer.h"
 35#include "llfile.h"
 36
 37class	LLSD;
 38
 39// Set this if longer stats are needed
 40#define ENABLE_LONG_TIME_STATS	0
 41
 42//
 43// Accumulates statistics for an arbitrary length of time.
 44// Does this by maintaining a chain of accumulators, each one
 45// accumulation the results of the parent.  Can scale to arbitrary
 46// amounts of time with very low memory cost.
 47//
 48
 49class LL_COMMON_API LLStatAccum
 50{
 51protected:
 52	LLStatAccum(bool use_frame_timer);
 53	virtual ~LLStatAccum();
 54
 55public:
 56	enum TimeScale {
 57		SCALE_100MS,
 58		SCALE_SECOND,
 59		SCALE_MINUTE,
 60#if ENABLE_LONG_TIME_STATS
 61		SCALE_HOUR,
 62		SCALE_DAY,
 63		SCALE_WEEK,
 64#endif
 65		NUM_SCALES,			// Use to size storage arrays
 66		SCALE_PER_FRAME		// For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets
 67	};
 68
 69	static U64 sScaleTimes[NUM_SCALES];
 70
 71	virtual F32 meanValue(TimeScale scale) const;
 72		// see the subclasses for the specific meaning of value
 73
 74	F32 meanValueOverLast100ms()  const { return meanValue(SCALE_100MS);  }
 75	F32 meanValueOverLastSecond() const	{ return meanValue(SCALE_SECOND); }
 76	F32 meanValueOverLastMinute() const	{ return meanValue(SCALE_MINUTE); }
 77
 78	void reset(U64 when);
 79
 80	void sum(F64 value);
 81	void sum(F64 value, U64 when);
 82
 83	U64 getCurrentUsecs() const;
 84		// Get current microseconds based on timer type
 85
 86	BOOL	mUseFrameTimer;
 87	BOOL	mRunning;
 88
 89	U64		mLastTime;
 90	
 91	struct Bucket
 92	{
 93		Bucket() :
 94			accum(0.0),
 95			endTime(0),
 96			lastValid(false),
 97			lastAccum(0.0)
 98		{}
 99
100		F64	accum;
101		U64	endTime;
102
103		bool	lastValid;
104		F64	lastAccum;
105	};
106
107	Bucket	mBuckets[NUM_SCALES];
108
109	BOOL 	mLastSampleValid;
110	F64 	mLastSampleValue;
111};
112
113class LL_COMMON_API LLStatMeasure : public LLStatAccum
114	// gathers statistics about things that are measured
115	// ex.: tempature, time dilation
116{
117public:
118	LLStatMeasure(bool use_frame_timer = true);
119
120	void sample(F64);
121	void sample(S32 v) { sample((F64)v); }
122	void sample(U32 v) { sample((F64)v); }
123	void sample(S64 v) { sample((F64)v); }
124	void sample(U64 v) { sample((F64)v); }
125};
126
127
128class LL_COMMON_API LLStatRate : public LLStatAccum
129	// gathers statistics about things that can be counted over time
130	// ex.: LSL instructions executed, messages sent, simulator frames completed
131	// renders it in terms of rate of thing per second
132{
133public:
134	LLStatRate(bool use_frame_timer = true);
135
136	void count(U32);
137		// used to note that n items have occured
138	
139	void mark();
140		// used for counting the rate thorugh a point in the code
141};
142
143
144class LL_COMMON_API LLStatTime : public LLStatAccum
145	// gathers statistics about time spent in a block of code
146	// measure average duration per second in the block
147{
148public:
149	LLStatTime( const std::string & key = "undefined" );
150
151	U32		mFrameNumber;		// Current frame number
152	U64		mTotalTimeInFrame;	// Total time (microseconds) accumulated during the last frame
153
154	void	setKey( const std::string & key )		{ mKey = key;	};
155
156	virtual F32 meanValue(TimeScale scale) const;
157
158private:
159	void start();				// Start and stop measuring time block
160	void stop();
161
162	std::string		mKey;		// Tag representing this time block
163
164#if LL_DEBUG
165	BOOL			mRunning;	// TRUE if start() has been called
166#endif
167
168	friend class LLPerfBlock;
169};
170
171// ----------------------------------------------------------------------------
172
173
174// Use this class on the stack to record statistics about an area of code
175class LL_COMMON_API LLPerfBlock
176{
177public:
178    struct StatEntry
179    {
180            StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {}
181            LLStatTime  mStat;
182            U32         mCount;
183    };
184    typedef std::map<std::string, StatEntry*>		stat_map_t;
185
186	// Use this constructor for pre-defined LLStatTime objects
187	LLPerfBlock(LLStatTime* stat);
188
189	// Use this constructor for normal, optional LLPerfBlock time slices
190	LLPerfBlock( const char* key );
191
192	// Use this constructor for dynamically created LLPerfBlock time slices
193	// that are only enabled by specific control flags
194	LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS );
195
196	~LLPerfBlock();
197
198	enum
199	{	// Stats bitfield flags
200		LLSTATS_NO_OPTIONAL_STATS	= 0x00,		// No optional stats gathering, just pre-defined LLStatTime objects
201		LLSTATS_BASIC_STATS			= 0x01,		// Gather basic optional runtime stats
202		LLSTATS_SCRIPT_FUNCTIONS	= 0x02,		// Include LSL function calls
203	};
204	static void setStatsFlags( S32 flags )	{ sStatsFlags = flags;	};
205	static S32  getStatsFlags()				{ return sStatsFlags;	};
206
207	static void clearDynamicStats();		// Reset maps to clear out dynamic objects
208	static void addStatsToLLSDandReset( LLSD & stats,		// Get current information and clear time bin
209										LLStatAccum::TimeScale scale );
210
211private:
212	// Initialize dynamically created LLStatTime objects
213    void initDynamicStat(const std::string& key);
214
215	std::string				mLastPath;				// Save sCurrentStatPath when this is called
216	LLStatTime * 			mPredefinedStat;		// LLStatTime object to get data
217	StatEntry *				mDynamicStat;   		// StatEntryobject to get data
218
219	static S32				sStatsFlags;			// Control what is being recorded
220    static stat_map_t		sStatMap;				// Map full path string to LLStatTime objects
221	static std::string		sCurrentStatPath;		// Something like "frame/physics/physics step"
222};
223
224// ----------------------------------------------------------------------------
225
226class LL_COMMON_API LLPerfStats
227{
228public:
229    LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0);
230    virtual ~LLPerfStats();
231
232    virtual void init();    // Reset and start all stat timers
233    virtual void updatePerFrameStats();
234    // Override these function to add process-specific information to the performance log header and per-frame logging.
235    virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ }
236    virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ }
237
238    // High-resolution frame stats
239    BOOL    frameStatsIsRunning()                                { return (mReportPerformanceStatEnd > 0.);        };
240    F32     getReportPerformanceInterval() const                { return mReportPerformanceStatInterval;        };
241    void    setReportPerformanceInterval( F32 interval )        { mReportPerformanceStatInterval = interval;    };
242    void    setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS );
243    void    setProcessName(const std::string& process_name) { mProcessName = process_name; }
244    void    setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
245
246protected:
247    void    openPerfStatsFile();                    // Open file for high resolution metrics logging
248    void    dumpIntervalPerformanceStats();
249
250    llofstream      mFrameStatsFile;            // File for per-frame stats
251    BOOL            mFrameStatsFileFailure;        // Flag to prevent repeat opening attempts
252    BOOL            mSkipFirstFrameStats;        // Flag to skip one (partial) frame report
253    std::string     mProcessName;
254    S32             mProcessPID;
255
256private:
257    F32 mReportPerformanceStatInterval;    // Seconds between performance stats
258    F64 mReportPerformanceStatEnd;        // End time (seconds) for performance stats
259};
260
261// ----------------------------------------------------------------------------
262class LL_COMMON_API LLStat
263{
264private:
265	typedef std::multimap<std::string, LLStat*> stat_map_t;
266	static stat_map_t sStatList;
267
268	void init();
269
270public:
271	LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE);
272	LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE);
273	~LLStat();
274
275	void reset();
276
277	void start();	// Start the timer for the current "frame", otherwise uses the time tracked from
278					// the last addValue
279	void addValue(const F32 value = 1.f); // Adds the current value being tracked, and tracks the DT.
280	void addValue(const S32 value) { addValue((F32)value); }
281	void addValue(const U32 value) { addValue((F32)value); }
282
283	void setBeginTime(const F64 time);
284	void addValueTime(const F64 time, const F32 value = 1.f);
285	
286	S32 getCurBin() const;
287	S32 getNextBin() const;
288	
289	F32 getCurrent() const;
290	F32 getCurrentPerSec() const;
291	F64 getCurrentBeginTime() const;
292	F64 getCurrentTime() const;
293	F32 getCurrentDuration() const;
294	
295	F32 getPrev(S32 age) const;				// Age is how many "addValues" previously - zero is current
296	F32 getPrevPerSec(S32 age) const;		// Age is how many "addValues" previously - zero is current
297	F64 getPrevBeginTime(S32 age) const;
298	F64 getPrevTime(S32 age) const;
299	
300	F32 getBin(S32 bin) const;
301	F32 getBinPerSec(S32 bin) const;
302	F64 getBinBeginTime(S32 bin) const;
303	F64 getBinTime(S32 bin) const;
304
305	F32 getMax() const;
306	F32 getMaxPerSec() const;
307	
308	F32 getMean() const;
309	F32 getMeanPerSec() const;
310	F32 getMeanDuration() const;
311
312	F32 getMin() const;
313	F32 getMinPerSec() const;
314	F32 getMinDuration() const;
315
316	F32 getSum() const;
317	F32 getSumDuration() const;
318
319	U32 getNumValues() const;
320	S32 getNumBins() const;
321
322	F64 getLastTime() const;
323private:
324	BOOL mUseFrameTimer;
325	U32 mNumValues;
326	U32 mNumBins;
327	F32 mLastValue;
328	F64 mLastTime;
329	F32 *mBins;
330	F64 *mBeginTime;
331	F64 *mTime;
332	F32 *mDT;
333	S32 mCurBin;
334	S32 mNextBin;
335	
336	std::string mName;
337
338	static LLTimer sTimer;
339	static LLFrameTimer sFrameTimer;
340	
341public:
342	static LLStat* getStat(const std::string& name)
343	{
344		// return the first stat that matches 'name'
345		stat_map_t::iterator iter = sStatList.find(name);
346		if (iter != sStatList.end())
347			return iter->second;
348		else
349			return NULL;
350	}
351};
352	
353#endif // LL_STAT_