llstat.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:27k
- /**
- * @file llstat.cpp
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2010, Linden Research, Inc.
- *
- * 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://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * 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://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * 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.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "llstat.h"
- #include "lllivefile.h"
- #include "llerrorcontrol.h"
- #include "llframetimer.h"
- #include "timing.h"
- #include "llsd.h"
- #include "llsdserialize.h"
- #include "llstl.h"
- #include "u64.h"
- // statics
- S32 LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS; // Control what is being recorded
- LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects
- std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step"
- LLStat::stat_map_t LLStat::sStatList;
- //------------------------------------------------------------------------
- // Live config file to trigger stats logging
- static const char STATS_CONFIG_FILE_NAME[] = "/dev/shm/simperf/simperf_proc_config.llsd";
- static const F32 STATS_CONFIG_REFRESH_RATE = 5.0; // seconds
- class LLStatsConfigFile : public LLLiveFile
- {
- public:
- LLStatsConfigFile()
- : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE),
- mChanged(false), mStatsp(NULL) { }
- static std::string filename();
-
- protected:
- /* virtual */ bool loadFile();
- public:
- void init(LLPerfStats* statsp);
- static LLStatsConfigFile& instance();
- // return the singleton stats config file
- bool mChanged;
- protected:
- LLPerfStats* mStatsp;
- };
- std::string LLStatsConfigFile::filename()
- {
- return STATS_CONFIG_FILE_NAME;
- }
- void LLStatsConfigFile::init(LLPerfStats* statsp)
- {
- mStatsp = statsp;
- }
- LLStatsConfigFile& LLStatsConfigFile::instance()
- {
- static LLStatsConfigFile the_file;
- return the_file;
- }
- /* virtual */
- // Load and parse the stats configuration file
- bool LLStatsConfigFile::loadFile()
- {
- if (!mStatsp)
- {
- llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl;
- return false;
- }
- mChanged = true;
-
- LLSD stats_config;
- {
- llifstream file(filename().c_str());
- if (file.is_open())
- {
- LLSDSerialize::fromXML(stats_config, file);
- if (stats_config.isUndefined())
- {
- llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl;
- mStatsp->setReportPerformanceDuration( 0.f );
- return false;
- }
- }
- else
- { // File went away, turn off stats if it was on
- if ( mStatsp->frameStatsIsRunning() )
- {
- llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl;
- mStatsp->setReportPerformanceDuration( 0.f );
- }
- return true;
- }
- }
- F32 duration = 0.f;
- F32 interval = 0.f;
- S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS;
- const char * w = "duration";
- if (stats_config.has(w))
- {
- duration = (F32)stats_config[w].asReal();
- }
- w = "interval";
- if (stats_config.has(w))
- {
- interval = (F32)stats_config[w].asReal();
- }
- w = "flags";
- if (stats_config.has(w))
- {
- flags = (S32)stats_config[w].asInteger();
- if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS &&
- duration > 0)
- { // No flags passed in, but have a duration, so reset to basic stats
- flags = LLPerfBlock::LLSTATS_BASIC_STATS;
- }
- }
- mStatsp->setReportPerformanceDuration( duration, flags );
- mStatsp->setReportPerformanceInterval( interval );
- if ( duration > 0 )
- {
- if ( interval == 0.f )
- {
- llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl;
- }
- else
- {
- llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl;
- }
- }
- else
- {
- llinfos << "Performance stats recording turned off" << llendl;
- }
- return true;
- }
- //------------------------------------------------------------------------
- LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) :
- mFrameStatsFileFailure(FALSE),
- mSkipFirstFrameStats(FALSE),
- mProcessName(process_name),
- mProcessPID(process_pid),
- mReportPerformanceStatInterval(1.f),
- mReportPerformanceStatEnd(0.0)
- { }
- LLPerfStats::~LLPerfStats()
- {
- LLPerfBlock::clearDynamicStats();
- mFrameStatsFile.close();
- }
- void LLPerfStats::init()
- {
- // Initialize the stats config file instance.
- (void) LLStatsConfigFile::instance().init(this);
- (void) LLStatsConfigFile::instance().checkAndReload();
- }
- // Open file for statistics
- void LLPerfStats::openPerfStatsFile()
- {
- if ( !mFrameStatsFile
- && !mFrameStatsFileFailure )
- {
- std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID);
- mFrameStatsFile.close();
- mFrameStatsFile.clear();
- mFrameStatsFile.open(stats_file, llofstream::out);
- if ( mFrameStatsFile.fail() )
- {
- llinfos << "Error opening statistics log file " << stats_file << llendl;
- mFrameStatsFileFailure = TRUE;
- }
- else
- {
- LLSD process_info = LLSD::emptyMap();
- process_info["name"] = mProcessName;
- process_info["pid"] = (LLSD::Integer) mProcessPID;
- process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval;
- // Add process-specific info.
- addProcessHeaderInfo(process_info);
- mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl;
- }
- }
- }
- // Dump out performance metrics over some time interval
- void LLPerfStats::dumpIntervalPerformanceStats()
- {
- // Ensure output file is OK
- openPerfStatsFile();
- if ( mFrameStatsFile )
- {
- LLSD stats = LLSD::emptyMap();
- LLStatAccum::TimeScale scale;
- if ( getReportPerformanceInterval() == 0.f )
- {
- scale = LLStatAccum::SCALE_PER_FRAME;
- }
- else if ( getReportPerformanceInterval() < 0.5f )
- {
- scale = LLStatAccum::SCALE_100MS;
- }
- else
- {
- scale = LLStatAccum::SCALE_SECOND;
- }
- // Write LLSD into log
- stats["utc_time"] = (LLSD::String) LLError::utcTime();
- stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000)); // milliseconds since epoch
- stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount();
- // Add process-specific frame info.
- addProcessFrameInfo(stats, scale);
- LLPerfBlock::addStatsToLLSDandReset( stats, scale );
- mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl;
- }
- }
- // Set length of performance stat recording.
- // If turning stats on, caller must provide flags
- void LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ )
- {
- if ( seconds <= 0.f )
- {
- mReportPerformanceStatEnd = 0.0;
- LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS); // Make sure all recording is off
- mFrameStatsFile.close();
- LLPerfBlock::clearDynamicStats();
- }
- else
- {
- mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
- // Clear failure flag to try and create the log file once
- mFrameStatsFileFailure = FALSE;
- mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame)
- LLPerfBlock::setStatsFlags(flags);
- }
- }
- void LLPerfStats::updatePerFrameStats()
- {
- (void) LLStatsConfigFile::instance().checkAndReload();
- static LLFrameTimer performance_stats_timer;
- if ( frameStatsIsRunning() )
- {
- if ( mReportPerformanceStatInterval == 0 )
- { // Record info every frame
- if ( mSkipFirstFrameStats )
- { // Skip the first time - was started this frame
- mSkipFirstFrameStats = FALSE;
- }
- else
- {
- dumpIntervalPerformanceStats();
- }
- }
- else
- {
- performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() );
- if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval ))
- {
- dumpIntervalPerformanceStats();
- }
- }
-
- if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd )
- { // Reached end of time, clear it to stop reporting
- setReportPerformanceDuration(0.f); // Don't set mReportPerformanceStatEnd directly
- llinfos << "Recording performance stats completed" << llendl;
- }
- }
- }
- //------------------------------------------------------------------------
- U64 LLStatAccum::sScaleTimes[NUM_SCALES] =
- {
- USEC_PER_SEC / 10, // 100 millisec
- USEC_PER_SEC * 1, // seconds
- USEC_PER_SEC * 60, // minutes
- #if ENABLE_LONG_TIME_STATS
- // enable these when more time scales are desired
- USEC_PER_SEC * 60*60, // hours
- USEC_PER_SEC * 24*60*60, // days
- USEC_PER_SEC * 7*24*60*60, // weeks
- #endif
- };
- LLStatAccum::LLStatAccum(bool useFrameTimer)
- : mUseFrameTimer(useFrameTimer),
- mRunning(FALSE),
- mLastTime(0),
- mLastSampleValue(0.0),
- mLastSampleValid(FALSE)
- {
- }
- LLStatAccum::~LLStatAccum()
- {
- }
- void LLStatAccum::reset(U64 when)
- {
- mRunning = TRUE;
- mLastTime = when;
- for (int i = 0; i < NUM_SCALES; ++i)
- {
- mBuckets[i].accum = 0.0;
- mBuckets[i].endTime = when + sScaleTimes[i];
- mBuckets[i].lastValid = false;
- }
- }
- void LLStatAccum::sum(F64 value)
- {
- sum(value, getCurrentUsecs());
- }
- void LLStatAccum::sum(F64 value, U64 when)
- {
- if (!mRunning)
- {
- reset(when);
- return;
- }
- if (when < mLastTime)
- {
- // This happens a LOT on some dual core systems.
- lldebugs << "LLStatAccum::sum clock has gone backwards from "
- << mLastTime << " to " << when << ", resetting" << llendl;
- reset(when);
- return;
- }
- // how long is this value for
- U64 timeSpan = when - mLastTime;
- for (int i = 0; i < NUM_SCALES; ++i)
- {
- Bucket& bucket = mBuckets[i];
- if (when < bucket.endTime)
- {
- bucket.accum += value;
- }
- else
- {
- U64 timeScale = sScaleTimes[i];
- U64 timeLeft = when - bucket.endTime;
- // how much time is left after filling this bucket
-
- if (timeLeft < timeScale)
- {
- F64 valueLeft = value * timeLeft / timeSpan;
- bucket.lastValid = true;
- bucket.lastAccum = bucket.accum + (value - valueLeft);
- bucket.accum = valueLeft;
- bucket.endTime += timeScale;
- }
- else
- {
- U64 timeTail = timeLeft % timeScale;
- bucket.lastValid = true;
- bucket.lastAccum = value * timeScale / timeSpan;
- bucket.accum = value * timeTail / timeSpan;
- bucket.endTime += (timeLeft - timeTail) + timeScale;
- }
- }
- }
- mLastTime = when;
- }
- F32 LLStatAccum::meanValue(TimeScale scale) const
- {
- if (!mRunning)
- {
- return 0.0;
- }
- if ( scale == SCALE_PER_FRAME )
- { // Per-frame not supported here
- scale = SCALE_100MS;
- }
- if (scale < 0 || scale >= NUM_SCALES)
- {
- llwarns << "llStatAccum::meanValue called for unsupported scale: "
- << scale << llendl;
- return 0.0;
- }
- const Bucket& bucket = mBuckets[scale];
- F64 value = bucket.accum;
- U64 timeLeft = bucket.endTime - mLastTime;
- U64 scaleTime = sScaleTimes[scale];
- if (bucket.lastValid)
- {
- value += bucket.lastAccum * timeLeft / scaleTime;
- }
- else if (timeLeft < scaleTime)
- {
- value *= scaleTime / (scaleTime - timeLeft);
- }
- else
- {
- value = 0.0;
- }
- return (F32)(value / scaleTime);
- }
- U64 LLStatAccum::getCurrentUsecs() const
- {
- if (mUseFrameTimer)
- {
- return LLFrameTimer::getTotalTime();
- }
- else
- {
- return totalTime();
- }
- }
- // ------------------------------------------------------------------------
- LLStatRate::LLStatRate(bool use_frame_timer)
- : LLStatAccum(use_frame_timer)
- {
- }
- void LLStatRate::count(U32 value)
- {
- sum((F64)value * sScaleTimes[SCALE_SECOND]);
- }
- void LLStatRate::mark()
- {
- // Effectively the same as count(1), but sets mLastSampleValue
- U64 when = getCurrentUsecs();
- if ( mRunning
- && (when > mLastTime) )
- { // Set mLastSampleValue to the time from the last mark()
- F64 duration = ((F64)(when - mLastTime)) / sScaleTimes[SCALE_SECOND];
- if ( duration > 0.0 )
- {
- mLastSampleValue = 1.0 / duration;
- }
- else
- {
- mLastSampleValue = 0.0;
- }
- }
- sum( (F64) sScaleTimes[SCALE_SECOND], when);
- }
- // ------------------------------------------------------------------------
- LLStatMeasure::LLStatMeasure(bool use_frame_timer)
- : LLStatAccum(use_frame_timer)
- {
- }
- void LLStatMeasure::sample(F64 value)
- {
- U64 when = getCurrentUsecs();
- if (mLastSampleValid)
- {
- F64 avgValue = (value + mLastSampleValue) / 2.0;
- F64 interval = (F64)(when - mLastTime);
- sum(avgValue * interval, when);
- }
- else
- {
- reset(when);
- }
- mLastSampleValid = TRUE;
- mLastSampleValue = value;
- }
- // ------------------------------------------------------------------------
- LLStatTime::LLStatTime(const std::string & key)
- : LLStatAccum(false),
- mFrameNumber(LLFrameTimer::getFrameCount()),
- mTotalTimeInFrame(0),
- mKey(key)
- #if LL_DEBUG
- , mRunning(FALSE)
- #endif
- {
- }
- void LLStatTime::start()
- {
- // Reset frame accumluation if the frame number has changed
- U32 frame_number = LLFrameTimer::getFrameCount();
- if ( frame_number != mFrameNumber )
- {
- mFrameNumber = frame_number;
- mTotalTimeInFrame = 0;
- }
- sum(0.0);
- #if LL_DEBUG
- // Shouldn't be running already
- llassert( !mRunning );
- mRunning = TRUE;
- #endif
- }
- void LLStatTime::stop()
- {
- U64 end_time = getCurrentUsecs();
- U64 duration = end_time - mLastTime;
- sum(F64(duration), end_time);
- //llinfos << "mTotalTimeInFrame incremented from " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl;
- mTotalTimeInFrame += duration;
- #if LL_DEBUG
- mRunning = FALSE;
- #endif
- }
- /* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const
- {
- if ( LLStatAccum::SCALE_PER_FRAME == scale )
- {
- return mTotalTimeInFrame;
- }
- else
- {
- return LLStatAccum::meanValue(scale);
- }
- }
- // ------------------------------------------------------------------------
- // Use this constructor for pre-defined LLStatTime objects
- LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL)
- {
- if (mPredefinedStat)
- {
- // If dynamic stats are turned on, this will create a separate entry in the stat map.
- initDynamicStat(mPredefinedStat->mKey);
- // Start predefined stats. These stats are not part of the stat map.
- mPredefinedStat->start();
- }
- }
- // Use this constructor for normal, optional LLPerfBlock time slices
- LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL)
- {
- if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0)
- { // These are off unless the base set is enabled
- return;
- }
- initDynamicStat(key);
- }
-
- // Use this constructor for dynamically created LLPerfBlock time slices
- // that are only enabled by specific control flags
- LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL)
- {
- if ((sStatsFlags & flags) == 0)
- {
- return;
- }
- if (NULL == key2 || strlen(key2) == 0)
- {
- initDynamicStat(key1);
- }
- else
- {
- std::ostringstream key;
- key << key1 << "_" << key2;
- initDynamicStat(key.str());
- }
- }
- // Set up the result data map if dynamic stats are enabled
- void LLPerfBlock::initDynamicStat(const std::string& key)
- {
- // Early exit if dynamic stats aren't enabled.
- if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS)
- return;
- mLastPath = sCurrentStatPath; // Save and restore current path
- sCurrentStatPath += "/" + key; // Add key to current path
- // See if the LLStatTime object already exists
- stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath);
- if ( iter == sStatMap.end() )
- {
- // StatEntry object doesn't exist, so create it
- mDynamicStat = new StatEntry( key );
- sStatMap[ sCurrentStatPath ] = mDynamicStat; // Set the entry for this path
- }
- else
- {
- // Found this path in the map, use the object there
- mDynamicStat = (*iter).second; // Get StatEntry for the current path
- }
- if (mDynamicStat)
- {
- mDynamicStat->mStat.start();
- mDynamicStat->mCount++;
- }
- else
- {
- llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl;
- sCurrentStatPath = mLastPath;
- }
- }
- // Destructor does the time accounting
- LLPerfBlock::~LLPerfBlock()
- {
- if (mPredefinedStat) mPredefinedStat->stop();
- if (mDynamicStat)
- {
- mDynamicStat->mStat.stop();
- sCurrentStatPath = mLastPath; // Restore the path in case sStatsEnabled changed during this block
- }
- }
- // Clear the map of any dynamic stats. Static routine
- void LLPerfBlock::clearDynamicStats()
- {
- std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer());
- sStatMap.clear();
- }
- // static - Extract the stat info into LLSD
- void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
- LLStatAccum::TimeScale scale )
- {
- // If we aren't in per-frame scale, we need to go from second to microsecond.
- U32 scale_adjustment = 1;
- if (LLStatAccum::SCALE_PER_FRAME != scale)
- {
- scale_adjustment = USEC_PER_SEC;
- }
- stat_map_t::iterator iter = sStatMap.begin();
- for ( ; iter != sStatMap.end(); ++iter )
- { // Put the entry into LLSD "/full/path/to/stat/" = microsecond total time
- const std::string & stats_full_path = (*iter).first;
- StatEntry * stat = (*iter).second;
- if (stat)
- {
- if (stat->mCount > 0)
- {
- stats[stats_full_path] = LLSD::emptyMap();
- stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale));
- if (stat->mCount > 1)
- {
- stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount;
- }
- stat->mCount = 0;
- }
- }
- else
- { // WTF? Shouldn't have a NULL pointer in the map.
- llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
- }
- }
- }
- // ------------------------------------------------------------------------
- LLTimer LLStat::sTimer;
- LLFrameTimer LLStat::sFrameTimer;
- void LLStat::init()
- {
- llassert(mNumBins > 0);
- mNumValues = 0;
- mLastValue = 0.f;
- mLastTime = 0.f;
- mCurBin = (mNumBins-1);
- mNextBin = 0;
- mBins = new F32[mNumBins];
- mBeginTime = new F64[mNumBins];
- mTime = new F64[mNumBins];
- mDT = new F32[mNumBins];
- for (U32 i = 0; i < mNumBins; i++)
- {
- mBins[i] = 0.f;
- mBeginTime[i] = 0.0;
- mTime[i] = 0.0;
- mDT[i] = 0.f;
- }
- if (!mName.empty())
- {
- stat_map_t::iterator iter = sStatList.find(mName);
- if (iter != sStatList.end())
- llwarns << "LLStat with duplicate name: " << mName << llendl;
- sStatList.insert(std::make_pair(mName, this));
- }
- }
- LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer)
- : mUseFrameTimer(use_frame_timer),
- mNumBins(num_bins)
- {
- init();
- }
- LLStat::LLStat(std::string name, U32 num_bins, BOOL use_frame_timer)
- : mUseFrameTimer(use_frame_timer),
- mNumBins(num_bins),
- mName(name)
- {
- init();
- }
- LLStat::~LLStat()
- {
- delete[] mBins;
- delete[] mBeginTime;
- delete[] mTime;
- delete[] mDT;
- if (!mName.empty())
- {
- // handle multiple entries with the same name
- stat_map_t::iterator iter = sStatList.find(mName);
- while (iter != sStatList.end() && iter->second != this)
- ++iter;
- sStatList.erase(iter);
- }
- }
- void LLStat::reset()
- {
- U32 i;
- mNumValues = 0;
- mLastValue = 0.f;
- mCurBin = (mNumBins-1);
- delete[] mBins;
- delete[] mBeginTime;
- delete[] mTime;
- delete[] mDT;
- mBins = new F32[mNumBins];
- mBeginTime = new F64[mNumBins];
- mTime = new F64[mNumBins];
- mDT = new F32[mNumBins];
- for (i = 0; i < mNumBins; i++)
- {
- mBins[i] = 0.f;
- mBeginTime[i] = 0.0;
- mTime[i] = 0.0;
- mDT[i] = 0.f;
- }
- }
- void LLStat::setBeginTime(const F64 time)
- {
- mBeginTime[mNextBin] = time;
- }
- void LLStat::addValueTime(const F64 time, const F32 value)
- {
- if (mNumValues < mNumBins)
- {
- mNumValues++;
- }
- // Increment the bin counters.
- mCurBin++;
- if ((U32)mCurBin == mNumBins)
- {
- mCurBin = 0;
- }
- mNextBin++;
- if ((U32)mNextBin == mNumBins)
- {
- mNextBin = 0;
- }
- mBins[mCurBin] = value;
- mTime[mCurBin] = time;
- mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]);
- //this value is used to prime the min/max calls
- mLastTime = mTime[mCurBin];
- mLastValue = value;
- // Set the begin time for the next stat segment.
- mBeginTime[mNextBin] = mTime[mCurBin];
- mTime[mNextBin] = mTime[mCurBin];
- mDT[mNextBin] = 0.f;
- }
- void LLStat::start()
- {
- if (mUseFrameTimer)
- {
- mBeginTime[mNextBin] = sFrameTimer.getElapsedSeconds();
- }
- else
- {
- mBeginTime[mNextBin] = sTimer.getElapsedTimeF64();
- }
- }
- void LLStat::addValue(const F32 value)
- {
- if (mNumValues < mNumBins)
- {
- mNumValues++;
- }
- // Increment the bin counters.
- mCurBin++;
- if ((U32)mCurBin == mNumBins)
- {
- mCurBin = 0;
- }
- mNextBin++;
- if ((U32)mNextBin == mNumBins)
- {
- mNextBin = 0;
- }
- mBins[mCurBin] = value;
- if (mUseFrameTimer)
- {
- mTime[mCurBin] = sFrameTimer.getElapsedSeconds();
- }
- else
- {
- mTime[mCurBin] = sTimer.getElapsedTimeF64();
- }
- mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]);
- //this value is used to prime the min/max calls
- mLastTime = mTime[mCurBin];
- mLastValue = value;
- // Set the begin time for the next stat segment.
- mBeginTime[mNextBin] = mTime[mCurBin];
- mTime[mNextBin] = mTime[mCurBin];
- mDT[mNextBin] = 0.f;
- }
- F32 LLStat::getMax() const
- {
- U32 i;
- F32 current_max = mLastValue;
- if (mNumBins == 0)
- {
- current_max = 0.f;
- }
- else
- {
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- if (mBins[i] > current_max)
- {
- current_max = mBins[i];
- }
- }
- }
- return current_max;
- }
- F32 LLStat::getMean() const
- {
- U32 i;
- F32 current_mean = 0.f;
- U32 samples = 0;
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- current_mean += mBins[i];
- samples++;
- }
- // There will be a wrap error at 2^32. :)
- if (samples != 0)
- {
- current_mean /= samples;
- }
- else
- {
- current_mean = 0.f;
- }
- return current_mean;
- }
- F32 LLStat::getMin() const
- {
- U32 i;
- F32 current_min = mLastValue;
- if (mNumBins == 0)
- {
- current_min = 0.f;
- }
- else
- {
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- if (mBins[i] < current_min)
- {
- current_min = mBins[i];
- }
- }
- }
- return current_min;
- }
- F32 LLStat::getSum() const
- {
- U32 i;
- F32 sum = 0.f;
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- sum += mBins[i];
- }
- return sum;
- }
- F32 LLStat::getSumDuration() const
- {
- U32 i;
- F32 sum = 0.f;
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- sum += mDT[i];
- }
- return sum;
- }
- F32 LLStat::getPrev(S32 age) const
- {
- S32 bin;
- bin = mCurBin - age;
- while (bin < 0)
- {
- bin += mNumBins;
- }
- if (bin == mNextBin)
- {
- // Bogus for bin we're currently working on.
- return 0.f;
- }
- return mBins[bin];
- }
- F32 LLStat::getPrevPerSec(S32 age) const
- {
- S32 bin;
- bin = mCurBin - age;
- while (bin < 0)
- {
- bin += mNumBins;
- }
- if (bin == mNextBin)
- {
- // Bogus for bin we're currently working on.
- return 0.f;
- }
- return mBins[bin] / mDT[bin];
- }
- F64 LLStat::getPrevBeginTime(S32 age) const
- {
- S32 bin;
- bin = mCurBin - age;
- while (bin < 0)
- {
- bin += mNumBins;
- }
- if (bin == mNextBin)
- {
- // Bogus for bin we're currently working on.
- return 0.f;
- }
- return mBeginTime[bin];
- }
- F64 LLStat::getPrevTime(S32 age) const
- {
- S32 bin;
- bin = mCurBin - age;
- while (bin < 0)
- {
- bin += mNumBins;
- }
- if (bin == mNextBin)
- {
- // Bogus for bin we're currently working on.
- return 0.f;
- }
- return mTime[bin];
- }
- F32 LLStat::getBin(S32 bin) const
- {
- return mBins[bin];
- }
- F32 LLStat::getBinPerSec(S32 bin) const
- {
- return mBins[bin] / mDT[bin];
- }
- F64 LLStat::getBinBeginTime(S32 bin) const
- {
- return mBeginTime[bin];
- }
- F64 LLStat::getBinTime(S32 bin) const
- {
- return mTime[bin];
- }
- F32 LLStat::getCurrent() const
- {
- return mBins[mCurBin];
- }
- F32 LLStat::getCurrentPerSec() const
- {
- return mBins[mCurBin] / mDT[mCurBin];
- }
- F64 LLStat::getCurrentBeginTime() const
- {
- return mBeginTime[mCurBin];
- }
- F64 LLStat::getCurrentTime() const
- {
- return mTime[mCurBin];
- }
- F32 LLStat::getCurrentDuration() const
- {
- return mDT[mCurBin];
- }
- F32 LLStat::getMeanPerSec() const
- {
- U32 i;
- F32 value = 0.f;
- F32 dt = 0.f;
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- value += mBins[i];
- dt += mDT[i];
- }
- if (dt > 0.f)
- {
- return value/dt;
- }
- else
- {
- return 0.f;
- }
- }
- F32 LLStat::getMeanDuration() const
- {
- F32 dur = 0.0f;
- U32 count = 0;
- for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++)
- {
- if (i == (U32)mNextBin)
- {
- continue;
- }
- dur += mDT[i];
- count++;
- }
- if (count > 0)
- {
- dur /= F32(count);
- return dur;
- }
- else
- {
- return 0.f;
- }
- }
- F32 LLStat::getMaxPerSec() const
- {
- U32 i;
- F32 value;
- if (mNextBin != 0)
- {
- value = mBins[0]/mDT[0];
- }
- else if (mNumValues > 0)
- {
- value = mBins[1]/mDT[1];
- }
- else
- {
- value = 0.f;
- }
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- value = llmax(value, mBins[i]/mDT[i]);
- }
- return value;
- }
- F32 LLStat::getMinPerSec() const
- {
- U32 i;
- F32 value;
-
- if (mNextBin != 0)
- {
- value = mBins[0]/mDT[0];
- }
- else if (mNumValues > 0)
- {
- value = mBins[1]/mDT[1];
- }
- else
- {
- value = 0.f;
- }
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == (U32)mNextBin)
- {
- continue;
- }
- value = llmin(value, mBins[i]/mDT[i]);
- }
- return value;
- }
- F32 LLStat::getMinDuration() const
- {
- F32 dur = 0.0f;
- for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++)
- {
- dur = llmin(dur, mDT[i]);
- }
- return dur;
- }
- U32 LLStat::getNumValues() const
- {
- return mNumValues;
- }
- S32 LLStat::getNumBins() const
- {
- return mNumBins;
- }
- S32 LLStat::getCurBin() const
- {
- return mCurBin;
- }
- S32 LLStat::getNextBin() const
- {
- return mNextBin;
- }
- F64 LLStat::getLastTime() const
- {
- return mLastTime;
- }