llstat.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 
00033 #include "llstat.h"
00034 #include "llframetimer.h"
00035 #include "timing.h"
00036 
00037 class LLStatAccum::impl
00038 {
00039 public:
00040         static const TimeScale IMPL_NUM_SCALES = (TimeScale)(SCALE_TWO_MINUTE + 1);
00041         static U64 sScaleTimes[IMPL_NUM_SCALES];
00042 
00043         BOOL    mUseFrameTimer;
00044 
00045         BOOL    mRunning;
00046         U64             mLastTime;
00047         
00048         struct Bucket
00049         {
00050                 F64             accum;
00051                 U64             endTime;
00052 
00053                 BOOL    lastValid;
00054                 F64             lastAccum;
00055         };
00056 
00057         Bucket  mBuckets[IMPL_NUM_SCALES];
00058 
00059         BOOL    mLastSampleValid;
00060         F64     mLastSampleValue;
00061 
00062 
00063         impl(bool useFrameTimer);
00064 
00065         void reset(U64 when);
00066 
00067         void sum(F64 value);
00068         void sum(F64 value, U64 when);
00069 
00070         F32 meanValue(TimeScale scale) const;
00071 
00072         U64 getCurrentUsecs() const;
00073                 // Get current microseconds based on timer type
00074 };
00075 
00076 
00077 U64 LLStatAccum::impl::sScaleTimes[IMPL_NUM_SCALES] =
00078 {
00079         USEC_PER_SEC * 1,                               // seconds
00080         USEC_PER_SEC * 60,                              // minutes
00081         USEC_PER_SEC * 60 * 2                           // minutes
00082 #if 0
00083         // enable these when more time scales are desired
00084         USEC_PER_SEC * 60*60,                   // hours
00085         USEC_PER_SEC * 24*60*60,                // days
00086         USEC_PER_SEC * 7*24*60*60,              // weeks
00087 #endif
00088 };
00089 
00090 
00091 LLStatAccum::impl::impl(bool useFrameTimer)
00092 {
00093         mUseFrameTimer = useFrameTimer;
00094         mRunning = FALSE;
00095         mLastSampleValid = FALSE;
00096 }
00097 
00098 void LLStatAccum::impl::reset(U64 when)
00099 {
00100         mRunning = TRUE;
00101         mLastTime = when;
00102 
00103         for (int i = 0; i < IMPL_NUM_SCALES; ++i)
00104         {
00105                 mBuckets[i].accum = 0.0;
00106                 mBuckets[i].endTime = when + sScaleTimes[i];
00107                 mBuckets[i].lastValid = FALSE;
00108         }
00109 }
00110 
00111 void LLStatAccum::impl::sum(F64 value)
00112 {
00113         sum(value, getCurrentUsecs());
00114 }
00115 
00116 void LLStatAccum::impl::sum(F64 value, U64 when)
00117 {
00118         if (!mRunning)
00119         {
00120                 reset(when);
00121                 return;
00122         }
00123         if (when < mLastTime)
00124         {
00125                 // This happens a LOT on some dual core systems.
00126                 lldebugs << "LLStatAccum::sum clock has gone backwards from "
00127                         << mLastTime << " to " << when << ", resetting" << llendl;
00128 
00129                 reset(when);
00130                 return;
00131         }
00132 
00133         for (int i = 0; i < IMPL_NUM_SCALES; ++i)
00134         {
00135                 Bucket& bucket = mBuckets[i];
00136 
00137                 if (when < bucket.endTime)
00138                 {
00139                         bucket.accum += value;
00140                 }
00141                 else
00142                 {
00143                         U64 timeScale = sScaleTimes[i];
00144 
00145                         U64 timeSpan = when - mLastTime;
00146                                 // how long is this value for
00147                         U64 timeLeft = when - bucket.endTime;
00148                                 // how much time is left after filling this bucket
00149                         
00150                         if (timeLeft < timeScale)
00151                         {
00152                                 F64 valueLeft = value * timeLeft / timeSpan;
00153 
00154                                 bucket.lastValid = TRUE;
00155                                 bucket.lastAccum = bucket.accum + (value - valueLeft);
00156                                 bucket.accum = valueLeft;
00157                                 bucket.endTime += timeScale;
00158                         }
00159                         else
00160                         {
00161                                 U64 timeTail = timeLeft % timeScale;
00162 
00163                                 bucket.lastValid = TRUE;
00164                                 bucket.lastAccum = value * timeScale / timeSpan;
00165                                 bucket.accum = value * timeTail / timeSpan;
00166                                 bucket.endTime += (timeLeft - timeTail) + timeScale;
00167                         }
00168                 }
00169         }
00170 
00171         mLastTime = when;
00172 }
00173 
00174 
00175 F32 LLStatAccum::impl::meanValue(TimeScale scale) const
00176 {
00177         if (!mRunning)
00178         {
00179                 return 0.0;
00180         }
00181         if (scale < 0 || scale >= IMPL_NUM_SCALES)
00182         {
00183                 llwarns << "llStatAccum::meanValue called for unsupported scale: "
00184                         << scale << llendl;
00185                 return 0.0;
00186         }
00187 
00188         const Bucket& bucket = mBuckets[scale];
00189 
00190         F64 value = bucket.accum;
00191         U64 timeLeft = bucket.endTime - mLastTime;
00192         U64 scaleTime = sScaleTimes[scale];
00193 
00194         if (bucket.lastValid)
00195         {
00196                 value += bucket.lastAccum * timeLeft / scaleTime;
00197         }
00198         else if (timeLeft < scaleTime)
00199         {
00200                 value *= scaleTime / (scaleTime - timeLeft);
00201         }
00202         else
00203         {
00204                 value = 0.0;
00205         }
00206 
00207         return (F32)(value / scaleTime);
00208 }
00209 
00210 
00211 U64 LLStatAccum::impl::getCurrentUsecs() const
00212 {
00213         if (mUseFrameTimer)
00214         {
00215                 return LLFrameTimer::getTotalTime();
00216         }
00217         else
00218         {
00219                 return totalTime();
00220         }
00221 }
00222 
00223 
00224 
00225 
00226 
00227 LLStatAccum::LLStatAccum(bool useFrameTimer)
00228         : m(* new impl(useFrameTimer))
00229 {
00230 }
00231 
00232 LLStatAccum::~LLStatAccum()
00233 {
00234         delete &m;
00235 }
00236 
00237 F32 LLStatAccum::meanValue(TimeScale scale) const
00238 {
00239         return m.meanValue(scale);
00240 }
00241 
00242 
00243 
00244 LLStatMeasure::LLStatMeasure(bool use_frame_timer)
00245         : LLStatAccum(use_frame_timer)
00246 {
00247 }
00248 
00249 void LLStatMeasure::sample(F64 value)
00250 {
00251         U64 when = m.getCurrentUsecs();
00252 
00253         if (m.mLastSampleValid)
00254         {
00255                 F64 avgValue = (value + m.mLastSampleValue) / 2.0;
00256                 F64 interval = (F64)(when - m.mLastTime);
00257 
00258                 m.sum(avgValue * interval, when);
00259         }
00260         else
00261         {
00262                 m.reset(when);
00263         }
00264 
00265         m.mLastSampleValid = TRUE;
00266         m.mLastSampleValue = value;
00267 }
00268 
00269 
00270 LLStatRate::LLStatRate(bool use_frame_timer)
00271         : LLStatAccum(use_frame_timer)
00272 {
00273 }
00274 
00275 void LLStatRate::count(U32 value)
00276 {
00277         m.sum((F64)value * impl::sScaleTimes[SCALE_SECOND]);
00278 }
00279 
00280 
00281 LLStatTime::LLStatTime(bool use_frame_timer)
00282         : LLStatAccum(use_frame_timer)
00283 {
00284 }
00285 
00286 void LLStatTime::start()
00287 {
00288         m.sum(0.0);
00289 }
00290 
00291 void LLStatTime::stop()
00292 {
00293         U64 endTime = m.getCurrentUsecs();
00294         m.sum((F64)(endTime - m.mLastTime), endTime);
00295 }
00296 
00297 
00298 
00299 LLTimer LLStat::sTimer;
00300 LLFrameTimer LLStat::sFrameTimer;
00301 
00302 LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer)
00303 {
00304         llassert(num_bins > 0);
00305         U32 i;
00306         mUseFrameTimer = use_frame_timer;
00307         mNumValues = 0;
00308         mLastValue = 0.f;
00309         mLastTime = 0.f;
00310         mNumBins = num_bins;
00311         mCurBin = (mNumBins-1);
00312         mNextBin = 0;
00313         mBins      = new F32[mNumBins];
00314         mBeginTime = new F64[mNumBins];
00315         mTime      = new F64[mNumBins];
00316         mDT        = new F32[mNumBins];
00317         for (i = 0; i < mNumBins; i++)
00318         {
00319                 mBins[i]      = 0.f;
00320                 mBeginTime[i] = 0.0;
00321                 mTime[i]      = 0.0;
00322                 mDT[i]        = 0.f;
00323         }
00324 }
00325 
00326 LLStat::~LLStat()
00327 {
00328         delete[] mBins;
00329         delete[] mBeginTime;
00330         delete[] mTime;
00331         delete[] mDT;
00332 }
00333 
00334 void LLStat::reset()
00335 {
00336         U32 i;
00337 
00338         mNumValues = 0;
00339         mLastValue = 0.f;
00340         mCurBin = (mNumBins-1);
00341         delete[] mBins;
00342         delete[] mBeginTime;
00343         delete[] mTime;
00344         delete[] mDT;
00345         mBins      = new F32[mNumBins];
00346         mBeginTime = new F64[mNumBins];
00347         mTime      = new F64[mNumBins];
00348         mDT        = new F32[mNumBins];
00349         for (i = 0; i < mNumBins; i++)
00350         {
00351                 mBins[i]      = 0.f;
00352                 mBeginTime[i] = 0.0;
00353                 mTime[i]      = 0.0;
00354                 mDT[i]        = 0.f;
00355         }
00356 }
00357 
00358 void LLStat::setBeginTime(const F64 time)
00359 {
00360         mBeginTime[mNextBin] = time;
00361 }
00362 
00363 void LLStat::addValueTime(const F64 time, const F32 value)
00364 {
00365         if (mNumValues < mNumBins)
00366         {
00367                 mNumValues++;
00368         }
00369 
00370         // Increment the bin counters.
00371         mCurBin++;
00372         if ((U32)mCurBin == mNumBins)
00373         {
00374                 mCurBin = 0;
00375         }
00376         mNextBin++;
00377         if ((U32)mNextBin == mNumBins)
00378         {
00379                 mNextBin = 0;
00380         }
00381 
00382         mBins[mCurBin] = value;
00383         mTime[mCurBin] = time;
00384         mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]);
00385         //this value is used to prime the min/max calls
00386         mLastTime = mTime[mCurBin];
00387         mLastValue = value;
00388 
00389         // Set the begin time for the next stat segment.
00390         mBeginTime[mNextBin] = mTime[mCurBin];
00391         mTime[mNextBin] = mTime[mCurBin];
00392         mDT[mNextBin] = 0.f;
00393 }
00394 
00395 void LLStat::start()
00396 {
00397         if (mUseFrameTimer)
00398         {
00399                 mBeginTime[mNextBin] = sFrameTimer.getElapsedSeconds();
00400         }
00401         else
00402         {
00403                 mBeginTime[mNextBin] = sTimer.getElapsedTimeF64();
00404         }
00405 }
00406 
00407 void LLStat::addValue(const F32 value)
00408 {
00409         if (mNumValues < mNumBins)
00410         {
00411                 mNumValues++;
00412         }
00413 
00414         // Increment the bin counters.
00415         mCurBin++;
00416         if ((U32)mCurBin == mNumBins)
00417         {
00418                 mCurBin = 0;
00419         }
00420         mNextBin++;
00421         if ((U32)mNextBin == mNumBins)
00422         {
00423                 mNextBin = 0;
00424         }
00425 
00426         mBins[mCurBin] = value;
00427         if (mUseFrameTimer)
00428         {
00429                 mTime[mCurBin] = sFrameTimer.getElapsedSeconds();
00430         }
00431         else
00432         {
00433                 mTime[mCurBin] = sTimer.getElapsedTimeF64();
00434         }
00435         mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]);
00436 
00437         //this value is used to prime the min/max calls
00438         mLastTime = mTime[mCurBin];
00439         mLastValue = value;
00440 
00441         // Set the begin time for the next stat segment.
00442         mBeginTime[mNextBin] = mTime[mCurBin];
00443         mTime[mNextBin] = mTime[mCurBin];
00444         mDT[mNextBin] = 0.f;
00445 }
00446 
00447 
00448 F32 LLStat::getMax() const
00449 {
00450         U32 i;
00451         F32 current_max = mLastValue;
00452         if (mNumBins == 0)
00453         {
00454                 current_max = 0.f;
00455         }
00456         else
00457         {
00458                 for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00459                 {
00460                         // Skip the bin we're currently filling.
00461                         if (i == (U32)mNextBin)
00462                         {
00463                                 continue;
00464                         }
00465                         if (mBins[i] > current_max)
00466                         {
00467                                 current_max = mBins[i];
00468                         }
00469                 }
00470         }
00471         return current_max;
00472 }
00473 
00474 F32 LLStat::getMean() const
00475 {
00476         U32 i;
00477         F32 current_mean = 0.f;
00478         U32 samples = 0;
00479         for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00480         {
00481                 // Skip the bin we're currently filling.
00482                 if (i == (U32)mNextBin)
00483                 {
00484                         continue;
00485                 }
00486                 current_mean += mBins[i];
00487                 samples++;
00488         }
00489 
00490         // There will be a wrap error at 2^32. :)
00491         if (samples != 0)
00492         {
00493                 current_mean /= samples;
00494         }
00495         else
00496         {
00497                 current_mean = 0.f;
00498         }
00499         return current_mean;
00500 }
00501 
00502 F32 LLStat::getMin() const
00503 {
00504         U32 i;
00505         F32 current_min = mLastValue;
00506 
00507         if (mNumBins == 0)
00508         {
00509                 current_min = 0.f;
00510         }
00511         else
00512         {
00513                 for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00514                 {
00515                         // Skip the bin we're currently filling.
00516                         if (i == (U32)mNextBin)
00517                         {
00518                                 continue;
00519                         }
00520                         if (mBins[i] < current_min)
00521                         {
00522                                 current_min = mBins[i];
00523                         }
00524                 }
00525         }
00526         return current_min;
00527 }
00528 
00529 F32 LLStat::getSum() const
00530 {
00531         U32 i;
00532         F32 sum = 0.f;
00533         for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00534         {
00535                 // Skip the bin we're currently filling.
00536                 if (i == (U32)mNextBin)
00537                 {
00538                         continue;
00539                 }
00540                 sum += mBins[i];
00541         }
00542 
00543         return sum;
00544 }
00545 
00546 F32 LLStat::getSumDuration() const
00547 {
00548         U32 i;
00549         F32 sum = 0.f;
00550         for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00551         {
00552                 // Skip the bin we're currently filling.
00553                 if (i == (U32)mNextBin)
00554                 {
00555                         continue;
00556                 }
00557                 sum += mDT[i];
00558         }
00559 
00560         return sum;
00561 }
00562 
00563 F32 LLStat::getPrev(S32 age) const
00564 {
00565         S32 bin;
00566         bin = mCurBin - age;
00567 
00568         while (bin < 0)
00569         {
00570                 bin += mNumBins;
00571         }
00572 
00573         if (bin == mNextBin)
00574         {
00575                 // Bogus for bin we're currently working on.
00576                 return 0.f;
00577         }
00578         return mBins[bin];
00579 }
00580 
00581 F32 LLStat::getPrevPerSec(S32 age) const
00582 {
00583         S32 bin;
00584         bin = mCurBin - age;
00585 
00586         while (bin < 0)
00587         {
00588                 bin += mNumBins;
00589         }
00590 
00591         if (bin == mNextBin)
00592         {
00593                 // Bogus for bin we're currently working on.
00594                 return 0.f;
00595         }
00596         return mBins[bin] / mDT[bin];
00597 }
00598 
00599 F64 LLStat::getPrevBeginTime(S32 age) const
00600 {
00601         S32 bin;
00602         bin = mCurBin - age;
00603 
00604         while (bin < 0)
00605         {
00606                 bin += mNumBins;
00607         }
00608 
00609         if (bin == mNextBin)
00610         {
00611                 // Bogus for bin we're currently working on.
00612                 return 0.f;
00613         }
00614 
00615         return mBeginTime[bin];
00616 }
00617 
00618 F64 LLStat::getPrevTime(S32 age) const
00619 {
00620         S32 bin;
00621         bin = mCurBin - age;
00622 
00623         while (bin < 0)
00624         {
00625                 bin += mNumBins;
00626         }
00627 
00628         if (bin == mNextBin)
00629         {
00630                 // Bogus for bin we're currently working on.
00631                 return 0.f;
00632         }
00633 
00634         return mTime[bin];
00635 }
00636 
00637 F32 LLStat::getBin(S32 bin) const
00638 {
00639         return mBins[bin];
00640 }
00641 
00642 F32 LLStat::getBinPerSec(S32 bin) const
00643 {
00644         return mBins[bin] / mDT[bin];
00645 }
00646 
00647 F64 LLStat::getBinBeginTime(S32 bin) const
00648 {
00649         return mBeginTime[bin];
00650 }
00651 
00652 F64 LLStat::getBinTime(S32 bin) const
00653 {
00654         return mTime[bin];
00655 }
00656 
00657 F32 LLStat::getCurrent() const
00658 {
00659         return mBins[mCurBin];
00660 }
00661 
00662 F32 LLStat::getCurrentPerSec() const
00663 {
00664         return mBins[mCurBin] / mDT[mCurBin];
00665 }
00666 
00667 F64 LLStat::getCurrentBeginTime() const
00668 {
00669         return mBeginTime[mCurBin];
00670 }
00671 
00672 F64 LLStat::getCurrentTime() const
00673 {
00674         return mTime[mCurBin];
00675 }
00676 
00677 F32 LLStat::getCurrentDuration() const
00678 {
00679         return mDT[mCurBin];
00680 }
00681 
00682 F32 LLStat::getMeanPerSec() const
00683 {
00684         U32 i;
00685         F32 value = 0.f;
00686         F32 dt    = 0.f;
00687 
00688         for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00689         {
00690                 // Skip the bin we're currently filling.
00691                 if (i == (U32)mNextBin)
00692                 {
00693                         continue;
00694                 }
00695                 value += mBins[i];
00696                 dt    += mDT[i];
00697         }
00698 
00699         if (dt > 0.f)
00700         {
00701                 return value/dt;
00702         }
00703         else
00704         {
00705                 return 0.f;
00706         }
00707 }
00708 
00709 F32 LLStat::getMeanDuration() const
00710 {
00711         F32 dur = 0.0f;
00712         U32 count = 0;
00713         for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++)
00714         {
00715                 if (i == (U32)mNextBin)
00716                 {
00717                         continue;
00718                 }
00719                 dur += mDT[i];
00720                 count++;
00721         }
00722 
00723         if (count > 0)
00724         {
00725                 dur /= F32(count);
00726                 return dur;
00727         }
00728         else
00729         {
00730                 return 0.f;
00731         }
00732 }
00733 
00734 F32 LLStat::getMaxPerSec() const
00735 {
00736         U32 i;
00737         F32 value;
00738 
00739         if (mNextBin != 0)
00740         {
00741                 value = mBins[0]/mDT[0];
00742         }
00743         else if (mNumValues > 0)
00744         {
00745                 value = mBins[1]/mDT[1];
00746         }
00747         else
00748         {
00749                 value = 0.f;
00750         }
00751 
00752         for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00753         {
00754                 // Skip the bin we're currently filling.
00755                 if (i == (U32)mNextBin)
00756                 {
00757                         continue;
00758                 }
00759                 value = llmax(value, mBins[i]/mDT[i]);
00760         }
00761         return value;
00762 }
00763 
00764 F32 LLStat::getMinPerSec() const
00765 {
00766         U32 i;
00767         F32 value;
00768         
00769         if (mNextBin != 0)
00770         {
00771                 value = mBins[0]/mDT[0];
00772         }
00773         else if (mNumValues > 0)
00774         {
00775                 value = mBins[1]/mDT[1];
00776         }
00777         else
00778         {
00779                 value = 0.f;
00780         }
00781 
00782         for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
00783         {
00784                 // Skip the bin we're currently filling.
00785                 if (i == (U32)mNextBin)
00786                 {
00787                         continue;
00788                 }
00789                 value = llmin(value, mBins[i]/mDT[i]);
00790         }
00791         return value;
00792 }
00793 
00794 F32 LLStat::getMinDuration() const
00795 {
00796         F32 dur = 0.0f;
00797         for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++)
00798         {
00799                 dur = llmin(dur, mDT[i]);
00800         }
00801         return dur;
00802 }
00803 
00804 U32 LLStat::getNumValues() const
00805 {
00806         return mNumValues;
00807 }
00808 
00809 S32 LLStat::getNumBins() const
00810 {
00811         return mNumBins;
00812 }
00813 
00814 S32 LLStat::getCurBin() const
00815 {
00816         return mCurBin;
00817 }
00818 
00819 S32 LLStat::getNextBin() const
00820 {
00821         return mNextBin;
00822 }
00823 
00824 F64 LLStat::getLastTime() const
00825 {
00826         return mLastTime;
00827 }

Generated on Thu Jul 1 06:09:13 2010 for Second Life Viewer by  doxygen 1.4.7