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.mNumVisibleObjects = gPipeline.getVisibleCount();
00145 frame_data.mNumFullUpdates = gFullObjectUpdates;
00146 frame_data.mNumTerseUpdates = gTerseObjectUpdates;
00147
00148 gFullObjectUpdates = 0;
00149 gTerseObjectUpdates = 0;
00150
00151
00152 mFrameData.put(frame_data);
00153 if (mUseTimer)
00154 {
00155 if (mTimer.getElapsedTimeF32() > mStopTime)
00156 {
00157 llinfos << "Grabbed stats for " << mStopTime << " seconds, stopping and dumping" << llendl;
00158 setTrackStats(FALSE);
00159 }
00160 }
00161 }
00162
00163 void LLFrameStats::dump()
00164 {
00165 if (mFrameData.count())
00166 {
00167 F32 total_time = 0;
00168 S64 total_triangles = 0;
00169 S32 total_frames = mFrameData.count();
00170 S32 total_num_objects = 0;
00171 S32 total_visible_objects = 0;
00172
00173 time_t cur_time;
00174 char time_str[24];
00175
00176 time(&cur_time);
00177 strftime(time_str, 24, "%Y.%m.%d %H:%M:%S", localtime(&cur_time));
00178 time_str[19] = '\n';
00179 time_str[20] = '\0';
00180
00181 static S32 dump_count = 0;
00182
00183 char file_with_num[256];
00184 snprintf(file_with_num, sizeof(file_with_num), "fs%d.txt", dump_count);
00185 dump_count++;
00186
00187 char filename[LL_MAX_PATH];
00188 snprintf(filename, LL_MAX_PATH, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_with_num).c_str());
00189 FILE *fp = LLFile::fopen(filename, "w");
00190 if (!fp)
00191 {
00192 llinfos << "Couldn't open file for dumping frame stats!" << llendl;
00193 return;
00194 }
00195 llinfos << "Dumping frame statistics for " << mFrameData.count() << " frames" << llendl;
00196
00197 fprintf(fp, "Time\tNumTriangles\t");
00198
00199 S32 i;
00200 for (i = 0; i < NUM_STATS; i++)
00201 {
00202 fprintf(fp, "%s\t", sStatLabels[i]);
00203 }
00204 fprintf(fp, "Full Updates\tTerse Updates\tTotal Vorbis\tLong Vorbis\tNum Vorbis Decodes\t");
00205 fprintf(fp, "\n");
00206
00207 for (i = 0; i < mFrameData.count(); i++)
00208 {
00209 total_time += mFrameData[i].mTotalDuration;
00210 total_triangles += mFrameData[i].mNumTriangles;
00211 total_num_objects += mFrameData[i].mNumObjects;
00212 total_visible_objects += mFrameData[i].mNumVisibleObjects;
00213
00214 fprintf(fp, "%f\t%d\t", mFrameData[i].mTotalDuration, mFrameData[i].mNumTriangles);
00215 S32 j;
00216 for (j = 0; j < NUM_STATS; j++)
00217 {
00218 fprintf(fp, "%f\t", mFrameData[i].mDuration[j]);
00219 }
00220 fprintf(fp, "%d\t", mFrameData[i].mNumFullUpdates);
00221 fprintf(fp, "%d\t", mFrameData[i].mNumTerseUpdates);
00222 fprintf(fp, "%f\t", mFrameData[i].mTotalVorbisTime);
00223 fprintf(fp, "%f\t", mFrameData[i].mLongVorbisTime);
00224 fprintf(fp, "%d\t", mFrameData[i].mNumVorbisDecodes);
00225 fprintf(fp, "\n");
00226 }
00227 fclose(fp);
00228
00229
00230 snprintf(filename, LL_MAX_PATH, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, mSummaryFilename.c_str()).c_str());
00231 fp = LLFile::fopen(filename, "a");
00232 if (!fp)
00233 {
00234 llinfos << "Couldn't open file for dumping frame stats!" << llendl;
00235 return;
00236 }
00237
00238 fprintf(fp, "Performance data summary\n");
00239 fputs(time_str, fp);
00240
00241 fprintf(fp, "------------------------\n");
00242 fprintf(fp, "Total Time: %f\n", total_time);
00243 fprintf(fp, "Total Frames: %d\n", total_frames);
00244 fprintf(fp, "Total Triangles: %.0f\n", (F32)total_triangles);
00245 fprintf(fp, "Frames/sec: %f\n", total_frames / total_time);
00246 fprintf(fp, "Triangles/sec: %f\n", total_triangles/total_time);
00247 fprintf(fp, "Triangles/frame: %f\n", (F32)total_triangles/(F32)total_frames);
00248 fprintf(fp, "All Objects/frame: %f\n", (F32)total_num_objects/(F32)total_frames);
00249 fprintf(fp, "Vis Objects/frame: %f\n", (F32)total_visible_objects/(F32)total_frames);
00250 fprintf(fp, "\n");
00251 fclose(fp);
00252 }
00253 mFrameData.reset();
00254 }
00255
00256 void LLFrameStats::setTrackStats(const BOOL track_stats)
00257 {
00258 if (mTrackStats != track_stats)
00259 {
00260 if (!track_stats)
00261 {
00262 dump();
00263 }
00264 else
00265 {
00266 llinfos << "Enabling stat logging" << llendl;
00267 }
00268 }
00269
00270 if (track_stats)
00271 {
00272
00273 mFrameData.reset();
00274 }
00275 mTrackStats = track_stats;
00276 }
00277
00278
00279 void LLFrameStats::startLogging(void *)
00280 {
00281 gFrameStats.setTrackStats(TRUE);
00282 }
00283
00284 void LLFrameStats::stopLogging(void *)
00285 {
00286 gFrameStats.setTrackStats(FALSE);
00287 }
00288
00289 void LLFrameStats::timedLogging60(void *)
00290 {
00291 gFrameStats.setTrackStats(TRUE);
00292 gFrameStats.mTimer.reset();
00293 gFrameStats.mStopTime = 60.f;
00294 gFrameStats.mUseTimer = TRUE;
00295 }
00296
00297 void LLFrameStats::timedLogging30(void *)
00298 {
00299 gFrameStats.setTrackStats(TRUE);
00300 gFrameStats.mTimer.reset();
00301 gFrameStats.mStopTime = 30.f;
00302 gFrameStats.mUseTimer = TRUE;
00303 }
00304
00305 void LLFrameStats::timedLogging10(void *)
00306 {
00307 gFrameStats.setTrackStats(TRUE);
00308 gFrameStats.mTimer.reset();
00309 gFrameStats.mStopTime = 10.f;
00310 gFrameStats.mUseTimer = TRUE;
00311 }
00312
00313 const char *LLFrameStats::getCurStatName() const
00314 {
00315 return getStatLabel(mCurrentStat);
00316 }