00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llframestats.h"
00035 #include "v4color.h"
00036 #include "pipeline.h"
00037 #include "llviewerobjectlist.h"
00038 #include "lldrawpool.h"
00039 #include "lldir.h"
00040
00041 LLFrameStats gFrameStats;
00042
00043
00044 char *LLFrameStats::sStatLabels[NUM_STATS] = {
00045 "IdleNetwork",
00046 "AgentMisc",
00047 "ObjectUpdate",
00048 "CleanDead",
00049 "UpdateEffects",
00050 "ImageUpdate",
00051 "UpdateMove",
00052 "UpdateParticles",
00053 "UpdateCull",
00054 "UpdateGeom",
00055 "Audio",
00056 "UpdateTexStats",
00057 "StateSort",
00058 "Rebuild",
00059 "RenderSync",
00060 "RenderGeom",
00061 "RenderUI",
00062 "MiscEnd"
00063 };
00064
00065 LLColor4 LLFrameStats::sStatColors[NUM_STATS] = {
00066 LLColor4(0.0f, 0.5f, 1.0f, 0.5f),
00067 LLColor4(0.0f, 0.5f, 0.0f, 0.5f),
00068 LLColor4(0.0f, 0.0f, 1.0f, 0.5f),
00069 LLColor4(0.5f, 0.25f,0.5f, 0.5f),
00070 LLColor4(0.5f, 0.5f, 0.5f, 0.5f),
00071 LLColor4(0.5f, 1.0f, 0.0f, 0.5f),
00072 LLColor4(1.0f, 1.0f, 0.0f, 0.5f),
00073 LLColor4(0.0f, 0.0f, 1.0f, 0.5f),
00074 LLColor4(1.0f, 0.0f, 0.0f, 0.5f),
00075 LLColor4(0.5f, 0.0f, 0.0f, 0.5f),
00076 LLColor4(0.0f, 0.5f, 0.5f, 0.5f),
00077 LLColor4(0.5f, 1.0f, 1.0f, 0.5f),
00078 LLColor4(0.0f, 0.0f, 0.5f, 0.5f),
00079 LLColor4(1.0f, 0.0f, 1.0f, 0.5f),
00080 LLColor4(0.0f, 0.5f, 1.0f, 0.5f),
00081 LLColor4(1.0f, 1.0f, 1.0f, 0.5f),
00082 LLColor4(0.5f, 0.5f, 0.5f, 0.5f),
00083 LLColor4(1.0f, 0.0f, 0.0f, 0.5f)
00084 };
00085
00086 LLFrameStats::LLFrameStats()
00087 {
00088 mCurrentStat = NUM_STATS;
00089 mTrackStats = FALSE;
00090 mStopTime = FALSE;
00091 mUseTimer = FALSE;
00092 mStopTime = 0.f;
00093 mFilename = "frame_stats";
00094 }
00095
00096 LLFrameStats::~LLFrameStats()
00097 {
00098 mFrameData.reset();
00099 }
00100
00101 void LLFrameStats::start(const EStat stat)
00102 {
00103 stop();
00104 mCurrentStat = stat;
00105 mStats[stat].start();
00106 }
00107
00108 void LLFrameStats::stop()
00109 {
00110 if (NUM_STATS != mCurrentStat)
00111 {
00112 mStats[mCurrentStat].addValue();
00113 }
00114 }
00115
00116 extern S32 gFullObjectUpdates;
00117 extern S32 gTerseObjectUpdates;
00118
00119
00120 void LLFrameStats::addFrameData()
00121 {
00122 if (NUM_STATS == mCurrentStat)
00123 {
00124 return;
00125 }
00126 if (!mTrackStats)
00127 {
00128 return;
00129 }
00130
00131 static FrameData frame_data;
00132
00133 F32 total_duration = 0.f;
00134 S32 i;
00135 for (i = 0; i < NUM_STATS; i++)
00136 {
00137 frame_data.mDuration[i] = mStats[i].getCurrentDuration();
00138 total_duration += frame_data.mDuration[i];
00139 }
00140
00141 frame_data.mTotalDuration = total_duration;
00142 frame_data.mNumTriangles = gPipeline.mTrianglesDrawn;
00143 frame_data.mNumObjects = gObjectList.getNumObjects();
00144 frame_data.mNumFullUpdates = gFullObjectUpdates;
00145 frame_data.mNumTerseUpdates = gTerseObjectUpdates;
00146
00147 gFullObjectUpdates = 0;
00148 gTerseObjectUpdates = 0;
00149
00150
00151 mFrameData.put(frame_data);
00152 if (mUseTimer)
00153 {
00154 if (mTimer.getElapsedTimeF32() > mStopTime)
00155 {
00156 llinfos << "Grabbed stats for " << mStopTime << " seconds, stopping and dumping" << llendl;
00157 setTrackStats(FALSE);
00158 }
00159 }
00160 }
00161
00162 void LLFrameStats::dump()
00163 {
00164 if (mFrameData.count())
00165 {
00166 F32 total_time = 0;
00167 S64 total_triangles = 0;
00168 S32 total_frames = mFrameData.count();
00169 S32 total_num_objects = 0;
00170
00171 time_t cur_time;
00172 char time_str[24];
00173
00174 time(&cur_time);
00175 strftime(time_str, 24, "%Y.%m.%d %H:%M:%S", localtime(&cur_time));
00176 time_str[19] = '\n';
00177 time_str[20] = '\0';
00178
00179 static S32 dump_count = 0;
00180
00181 char file_with_num[256];
00182 snprintf(file_with_num, sizeof(file_with_num), "fs%d.txt", dump_count);
00183 dump_count++;
00184
00185 char filename[LL_MAX_PATH];
00186 snprintf(filename, LL_MAX_PATH, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_with_num).c_str());
00187 LLFILE *fp = LLFile::fopen(filename, "w");
00188 if (!fp)
00189 {
00190 llinfos << "Couldn't open file for dumping frame stats!" << llendl;
00191 return;
00192 }
00193 llinfos << "Dumping frame statistics for " << mFrameData.count() << " frames" << llendl;
00194
00195 fprintf(fp, "Time\tNumTriangles\t");
00196
00197 S32 i;
00198 for (i = 0; i < NUM_STATS; i++)
00199 {
00200 fprintf(fp, "%s\t", sStatLabels[i]);
00201 }
00202 fprintf(fp, "Full Updates\tTerse Updates\tTotal Vorbis\tLong Vorbis\tNum Vorbis Decodes\t");
00203 fprintf(fp, "\n");
00204
00205 for (i = 0; i < mFrameData.count(); i++)
00206 {
00207 total_time += mFrameData[i].mTotalDuration;
00208 total_triangles += mFrameData[i].mNumTriangles;
00209 total_num_objects += mFrameData[i].mNumObjects;
00210
00211 fprintf(fp, "%f\t%d\t", mFrameData[i].mTotalDuration, mFrameData[i].mNumTriangles);
00212 S32 j;
00213 for (j = 0; j < NUM_STATS; j++)
00214 {
00215 fprintf(fp, "%f\t", mFrameData[i].mDuration[j]);
00216 }
00217 fprintf(fp, "%d\t", mFrameData[i].mNumFullUpdates);
00218 fprintf(fp, "%d\t", mFrameData[i].mNumTerseUpdates);
00219 fprintf(fp, "%f\t", mFrameData[i].mTotalVorbisTime);
00220 fprintf(fp, "%f\t", mFrameData[i].mLongVorbisTime);
00221 fprintf(fp, "%d\t", mFrameData[i].mNumVorbisDecodes);
00222 fprintf(fp, "\n");
00223 }
00224 fclose(fp);
00225
00226
00227 snprintf(filename, LL_MAX_PATH, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, mSummaryFilename.c_str()).c_str());
00228 fp = LLFile::fopen(filename, "a");
00229 if (!fp)
00230 {
00231 llinfos << "Couldn't open file for dumping frame stats!" << llendl;
00232 return;
00233 }
00234
00235 fprintf(fp, "Performance data summary\n");
00236 fputs(time_str, fp);
00237
00238 fprintf(fp, "------------------------\n");
00239 fprintf(fp, "Total Time: %f\n", total_time);
00240 fprintf(fp, "Total Frames: %d\n", total_frames);
00241 fprintf(fp, "Total Triangles: %.0f\n", (F32)total_triangles);
00242 fprintf(fp, "Frames/sec: %f\n", total_frames / total_time);
00243 fprintf(fp, "Triangles/sec: %f\n", total_triangles/total_time);
00244 fprintf(fp, "Triangles/frame: %f\n", (F32)total_triangles/(F32)total_frames);
00245 fprintf(fp, "All Objects/frame: %f\n", (F32)total_num_objects/(F32)total_frames);
00246 fprintf(fp, "\n");
00247 fclose(fp);
00248 }
00249 mFrameData.reset();
00250 }
00251
00252 void LLFrameStats::setTrackStats(const BOOL track_stats)
00253 {
00254 if (mTrackStats != track_stats)
00255 {
00256 if (!track_stats)
00257 {
00258 dump();
00259 }
00260 else
00261 {
00262 llinfos << "Enabling stat logging" << llendl;
00263 }
00264 }
00265
00266 if (track_stats)
00267 {
00268
00269 mFrameData.reset();
00270 }
00271 mTrackStats = track_stats;
00272 }
00273
00274
00275 void LLFrameStats::startLogging(void *)
00276 {
00277 gFrameStats.setTrackStats(TRUE);
00278 }
00279
00280 void LLFrameStats::stopLogging(void *)
00281 {
00282 gFrameStats.setTrackStats(FALSE);
00283 }
00284
00285 void LLFrameStats::timedLogging60(void *)
00286 {
00287 gFrameStats.setTrackStats(TRUE);
00288 gFrameStats.mTimer.reset();
00289 gFrameStats.mStopTime = 60.f;
00290 gFrameStats.mUseTimer = TRUE;
00291 }
00292
00293 void LLFrameStats::timedLogging30(void *)
00294 {
00295 gFrameStats.setTrackStats(TRUE);
00296 gFrameStats.mTimer.reset();
00297 gFrameStats.mStopTime = 30.f;
00298 gFrameStats.mUseTimer = TRUE;
00299 }
00300
00301 void LLFrameStats::timedLogging10(void *)
00302 {
00303 gFrameStats.setTrackStats(TRUE);
00304 gFrameStats.mTimer.reset();
00305 gFrameStats.mStopTime = 10.f;
00306 gFrameStats.mUseTimer = TRUE;
00307 }
00308
00309 const char *LLFrameStats::getCurStatName() const
00310 {
00311 return getStatLabel(mCurrentStat);
00312 }