00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerstats.h"
00035 #include "llviewerthrottle.h"
00036 
00037 #include "message.h"
00038 #include "lltimer.h"
00039 
00040 LLViewerStats *gViewerStats = NULL;
00041 
00042 extern U32 gFrameCount;
00043 extern LLTimer gRenderStartTime;
00044 
00045 class StatAttributes
00046 {
00047 public:
00048         StatAttributes(const char *name,
00049                                    const BOOL enabled,
00050                                    const BOOL is_timer)
00051                 : mName(name),
00052                   mEnabled(enabled),
00053                   mIsTimer(is_timer)
00054         {
00055         }
00056         
00057         const char *mName;
00058         const BOOL mEnabled;
00059         const BOOL mIsTimer;
00060 };
00061 
00062 const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] =
00063 {
00064         
00065         StatAttributes("Version", TRUE, FALSE),
00066         
00067         StatAttributes("Seconds in Edit Appearence", FALSE, TRUE),
00068         
00069         StatAttributes("Seconds using Toolbox", FALSE, TRUE),
00070         
00071         StatAttributes("Chat messages sent", FALSE, FALSE),
00072         
00073         StatAttributes("IMs sent", FALSE, FALSE),
00074         
00075         StatAttributes("Fullscreen mode", FALSE, FALSE),
00076         
00077         StatAttributes("Object release count", FALSE, FALSE),
00078         
00079         StatAttributes("Object create count", FALSE, FALSE),
00080         
00081         StatAttributes("Object rez count", FALSE, FALSE),
00082         
00083         StatAttributes("Seconds below 10 FPS", FALSE, TRUE),
00084         
00085         StatAttributes("Seconds below 2 FPS", FALSE, TRUE),
00086         
00087         StatAttributes("Seconds in Mouselook", FALSE, TRUE),
00088         
00089         StatAttributes("Fly count", FALSE, FALSE),
00090         
00091         StatAttributes("Teleport count", FALSE, FALSE),
00092         
00093         StatAttributes("Objects deleted", FALSE, FALSE),
00094         
00095         StatAttributes("Snapshots taken", FALSE, FALSE),
00096         
00097         StatAttributes("Sounds uploaded", FALSE, FALSE),
00098         
00099         StatAttributes("Textures uploaded", FALSE, FALSE),
00100         
00101         StatAttributes("Changes to textures on objects", FALSE, FALSE),
00102         
00103         StatAttributes("Number of times killed", FALSE, FALSE),
00104         
00105         StatAttributes("Average delta between sucessive frame times", FALSE, FALSE),
00106         
00107         StatAttributes("Average delta between frame time and mean", FALSE, FALSE),
00108         
00109         StatAttributes("Inventory took too long to load", FALSE, FALSE),
00110         
00111         StatAttributes("Wearables took too long to load", FALSE, FALSE),
00112         
00113         StatAttributes("Time between LoginRequest and LoginReply", FALSE, FALSE),
00114         
00115         StatAttributes("Number of login attempts that timed out", FALSE, FALSE),
00116         
00117         StatAttributes("Known bad timer if != 0.0", FALSE, FALSE),
00118         
00119         StatAttributes("Number of times LLAssetStorage::getAssetData() has failed", FALSE, FALSE),
00120         
00121         StatAttributes("Number of times user has saved a script", FALSE, FALSE),
00122         
00123         StatAttributes("Animations uploaded", FALSE, FALSE),
00124         
00125         StatAttributes("Seconds below 8 FPS", FALSE, TRUE),
00126         
00127         StatAttributes("Seconds with sim FPS below 20", FALSE, TRUE),
00128         
00129         StatAttributes("Seconds with physics FPS below 20", FALSE, TRUE),
00130         
00131         StatAttributes("Seconds with packet loss > 5%", FALSE, TRUE),
00132         
00133         StatAttributes("Ratio of frames 2x longer than previous", FALSE, FALSE),
00134         
00135         StatAttributes("Vertex Buffers Enabled", TRUE, FALSE),
00136         
00137         StatAttributes("Increase/Decrease in bandwidth based on packet loss", FALSE, FALSE),
00138         
00139         StatAttributes("Max bandwidth setting", FALSE, FALSE),
00140         
00141         StatAttributes("Lighting Detail", FALSE, FALSE),
00142         
00143         StatAttributes("Visible Avatars", FALSE, FALSE),
00144         
00145         StatAttributes("Object Shaders", FALSE, FALSE),
00146         
00147         StatAttributes("Environment Shaders", FALSE, FALSE),
00148         
00149         StatAttributes("Draw Distance", FALSE, FALSE),
00150         
00151         StatAttributes("Chat Bubbles Enabled", FALSE, FALSE),
00152         
00153         StatAttributes("Avatar Shaders", FALSE, FALSE),
00154         
00155         StatAttributes("FRAME_SECS", FALSE, FALSE),
00156         
00157         StatAttributes("UPDATE_SECS", FALSE, FALSE),
00158         
00159         StatAttributes("NETWORK_SECS", FALSE, FALSE),
00160         
00161         StatAttributes("IMAGE_SECS", FALSE, FALSE),
00162         
00163         StatAttributes("REBUILD_SECS", FALSE, FALSE),
00164         
00165         StatAttributes("RENDER_SECS", FALSE, FALSE),
00166         
00167         StatAttributes("CROSSING_AVG", FALSE, FALSE),
00168         
00169         StatAttributes("CROSSING_MAX", FALSE, FALSE),
00170         
00171         StatAttributes("LibXUL Widget used", FALSE, FALSE),
00172         
00173         StatAttributes("Window width", FALSE, FALSE),
00174         
00175         StatAttributes("Window height", FALSE, FALSE),
00176         
00177         StatAttributes("Texture Bakes", FALSE, FALSE),
00178         
00179         StatAttributes("Texture Rebakes", FALSE, FALSE),
00180 
00181         
00182         StatAttributes("Logitech LCD", FALSE, FALSE)
00183 
00184 };
00185 
00186 LLViewerStats::LLViewerStats()
00187         : mPacketsLostPercentStat(64),
00188           mLastTimeDiff(0.0)
00189 {
00190         for (S32 i = 0; i < ST_COUNT; i++)
00191         {
00192                 mStats[i] = 0.0;
00193         }
00194         
00195         if (LLTimer::knownBadTimer())
00196         {
00197                 mStats[ST_HAS_BAD_TIMER] = 1.0;
00198         }       
00199 }
00200 
00201 LLViewerStats::~LLViewerStats()
00202 {
00203 }
00204 
00205 void LLViewerStats::resetStats()
00206 {
00207         gViewerStats->mKBitStat.reset();
00208         gViewerStats->mLayersKBitStat.reset();
00209         gViewerStats->mObjectKBitStat.reset();
00210         gViewerStats->mTextureKBitStat.reset();
00211         gViewerStats->mVFSPendingOperations.reset();
00212         gViewerStats->mAssetKBitStat.reset();
00213         gViewerStats->mPacketsInStat.reset();
00214         gViewerStats->mPacketsLostStat.reset();
00215         gViewerStats->mPacketsOutStat.reset();
00216         gViewerStats->mFPSStat.reset();
00217         gViewerStats->mTexturePacketsStat.reset();
00218 }
00219 
00220 
00221 F64 LLViewerStats::getStat(EStatType type) const
00222 {
00223         return mStats[type];
00224 }
00225 
00226 F64 LLViewerStats::setStat(EStatType type, F64 value)
00227 {
00228         mStats[type] = value;
00229         return mStats[type];
00230 }
00231 
00232 F64 LLViewerStats::incStat(EStatType type, F64 value)
00233 {
00234         mStats[type] += value;
00235         return mStats[type];
00236 }
00237 
00238 void LLViewerStats::updateFrameStats(const F64 time_diff)
00239 {
00240         if (mPacketsLostPercentStat.getCurrent() > 5.0)
00241         {
00242                 incStat(LLViewerStats::ST_LOSS_05_SECONDS, time_diff);
00243         }
00244         
00245         if (mSimFPS.getCurrent() < 20.f && mSimFPS.getCurrent() > 0.f)
00246         {
00247                 incStat(LLViewerStats::ST_SIM_FPS_20_SECONDS, time_diff);
00248         }
00249         
00250         if (mSimPhysicsFPS.getCurrent() < 20.f && mSimPhysicsFPS.getCurrent() > 0.f)
00251         {
00252                 incStat(LLViewerStats::ST_PHYS_FPS_20_SECONDS, time_diff);
00253         }
00254                 
00255         if (time_diff >= 0.5)
00256         {
00257                 incStat(LLViewerStats::ST_FPS_2_SECONDS, time_diff);
00258         }
00259         if (time_diff >= 0.125)
00260         {
00261                 incStat(LLViewerStats::ST_FPS_8_SECONDS, time_diff);
00262         }
00263         if (time_diff >= 0.1)
00264         {
00265                 incStat(LLViewerStats::ST_FPS_10_SECONDS, time_diff);
00266         }
00267 
00268         if (gFrameCount && mLastTimeDiff > 0.0)
00269         {
00270                 
00271                 setStat(LLViewerStats::ST_FPS_DROP_50_RATIO,
00272                                 (getStat(LLViewerStats::ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) + 
00273                                  (time_diff >= 2.0 * mLastTimeDiff ? 1.0 : 0.0)) / gFrameCount);
00274                         
00275 
00276                 
00277                 setStat(LLViewerStats::ST_FRAMETIME_JITTER,
00278                                 (getStat(LLViewerStats::ST_FRAMETIME_JITTER) * (gFrameCount - 1) + 
00279                                  fabs(mLastTimeDiff - time_diff) / mLastTimeDiff) / gFrameCount);
00280                         
00281                 F32 average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount;
00282                 setStat(LLViewerStats::ST_FRAMETIME_SLEW,
00283                                 (getStat(LLViewerStats::ST_FRAMETIME_SLEW) * (gFrameCount - 1) + 
00284                                  fabs(average_frametime - time_diff) / average_frametime) / gFrameCount);
00285 
00286                 F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
00287                 F32 delta_bandwidth = gViewerThrottle.getCurrentBandwidth() - max_bandwidth;
00288                 setStat(LLViewerStats::ST_DELTA_BANDWIDTH, delta_bandwidth / 1024.f);
00289 
00290                 setStat(LLViewerStats::ST_MAX_BANDWIDTH, max_bandwidth / 1024.f);
00291                 
00292         }
00293         
00294         mLastTimeDiff = time_diff;
00295 
00296 }
00297 
00298 void LLViewerStats::addToMessage(LLSD &body) const
00299 {
00300         LLSD &misc = body["misc"];
00301         
00302         for (S32 i = 0; i < ST_COUNT; i++)
00303         {
00304                 if (STAT_INFO[i].mEnabled)
00305                 {
00306                         
00307                         misc[STAT_INFO[i].mName] = mStats[i];
00308                         llinfos << "STAT: " << STAT_INFO[i].mName << ": " << mStats[i]
00309                                         << llendl;
00310                 }
00311         }
00312 }
00313 
00314 
00315 const char *LLViewerStats::statTypeToText(EStatType type)
00316 {
00317         if (type >= 0 && type < ST_COUNT)
00318         {
00319                 return STAT_INFO[type].mName;
00320         }
00321         else
00322         {
00323                 return "Unknown statistic";
00324         }
00325 }