Skip to content

Commit db49947

Browse files
authored
Merge pull request #4302 from secondlife/geenz/frametime-metric-improvements
First pass at adding expanded frametiming stats to the viewer.
2 parents e15a892 + e2227b9 commit db49947

File tree

4 files changed

+190
-2
lines changed

4 files changed

+190
-2
lines changed

indra/newview/app_settings/settings.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11488,6 +11488,28 @@
1148811488
<key>Value</key>
1148911489
<string>fss.txt</string>
1149011490
</map>
11491+
<key>StatsFrametimeSampleSeconds</key>
11492+
<map>
11493+
<key>Comment</key>
11494+
<string>The number of seconds to sample extended frametime data (percentiles, stddev).</string>
11495+
<key>Persist</key>
11496+
<integer>1</integer>
11497+
<key>Type</key>
11498+
<string>S32</string>
11499+
<key>Value</key>
11500+
<integer>5</integer>
11501+
</map>
11502+
<key>StatsFrametimeEventThreshold</key>
11503+
<map>
11504+
<key>Comment</key>
11505+
<string>The percentage that the frametime difference must exceed in order to register a frametime event. 0.1 = 10%, 0.25 = 25%, etc.</string>
11506+
<key>Persist</key>
11507+
<integer>1</integer>
11508+
<key>Type</key>
11509+
<string>F32</string>
11510+
<key>Value</key>
11511+
<real>0.1</real>
11512+
</map>
1149111513
<key>SystemLanguage</key>
1149211514
<map>
1149311515
<key>Comment</key>

indra/newview/llviewerstats.cpp

Lines changed: 129 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,16 @@ SimMeasurement<F64Megabytes > SIM_PHYSICS_MEM("physicsmemoryallocated", "", LL
220220

221221
LLTrace::SampleStatHandle<F64Milliseconds > FRAMETIME_JITTER("frametimejitter", "Average delta between successive frame times"),
222222
FRAMETIME("frametime", "Measured frame time"),
223-
SIM_PING("simpingstat");
223+
SIM_PING("simpingstat"),
224+
FRAMETIME_JITTER_99TH("frametimejitter99", "99th percentile of frametime jitter over the last 5 seconds."),
225+
FRAMETIME_JITTER_95TH("frametimejitter95", "99th percentile of frametime jitter over the last 5 seconds."),
226+
FRAMETIME_99TH("frametime99", "99th percentile of frametime over the last 5 seconds."),
227+
FRAMETIME_95TH("frametime95", "99th percentile of frametime over the last 5 seconds."),
228+
FRAMETIME_JITTER_CUMULATIVE("frametimejitcumulative", "Cumulative frametime jitter over the session."),
229+
FRAMETIME_JITTER_STDDEV("frametimejitterstddev", "Standard deviation of frametime jitter in a 5 second period."),
230+
FRAMETIME_STDDEV("frametimestddev", "Standard deviation of frametime in a 5 second period.");
231+
232+
LLTrace::SampleStatHandle<U32> FRAMETIME_JITTER_EVENTS("frametimeevents", "Number of frametime events in the session. Applies when jitter exceeds 10% of the previous frame.");
224233

225234
LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Meters> > AGENT_POSITION_SNAP("agentpositionsnap", "agent position corrections");
226235

@@ -272,8 +281,126 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff)
272281
// old stats that were never really used
273282
F64Seconds jit = (F64Seconds)std::fabs((mLastTimeDiff - time_diff));
274283
sample(LLStatViewer::FRAMETIME_JITTER, jit);
275-
}
284+
mTotalFrametimeJitter += jit;
285+
sample(LLStatViewer::FRAMETIME_JITTER_CUMULATIVE, mTotalFrametimeJitter);
286+
287+
static LLCachedControl<F32> frameTimeEventThreshold(gSavedSettings, "StatsFrametimeEventThreshold", 0.1f);
288+
289+
if (time_diff - mLastTimeDiff > mLastTimeDiff * frameTimeEventThreshold())
290+
{
291+
sample(LLStatViewer::FRAMETIME_JITTER_EVENTS, mFrameJitterEvents++);
292+
}
293+
294+
mFrameTimes.push_back(time_diff);
295+
mFrameTimesJitter.push_back(jit);
296+
297+
mLastFrameTimeSample += time_diff;
298+
299+
static LLCachedControl<S32> frameTimeSampleSeconds(gSavedSettings, "StatsFrametimeSampleSeconds", 5);
300+
301+
if (mLastFrameTimeSample >= frameTimeSampleSeconds())
302+
{
303+
// @TODO: This needs to be de-duped and moved into specific functions.
304+
// If we have more than 5 seconds of frame time samples, calculate the stddev, 99th percentile, and 95th percentile.
305+
std::sort(mFrameTimes.begin(), mFrameTimes.end());
306+
std::sort(mFrameTimesJitter.begin(), mFrameTimesJitter.end());
307+
F64Seconds ninety_ninth_percentile;
308+
F64Seconds ninety_fifth_percentile;
309+
310+
// Calculate standard deviation of mFrameTimes
311+
F64Seconds frame_time_stddev(0);
312+
if (mFrameTimes.size() > 1)
313+
{
314+
F64Seconds mean(0);
315+
for (const auto& v : mFrameTimes)
316+
{
317+
mean += v;
318+
}
319+
mean /= (F64)mFrameTimes.size();
320+
321+
F64Seconds variance(0);
322+
for (const auto& v : mFrameTimes)
323+
{
324+
F64Seconds diff = v - mean;
325+
F64 diff_squared;
326+
diff.value(diff_squared);
327+
diff_squared = std::pow(diff_squared, 2);
328+
variance += F64Seconds(diff_squared);
329+
}
330+
variance /= (F64)(mFrameTimes.size() - 1); // Use sample variance (n-1)
331+
F64 val;
332+
variance.value(val);
333+
frame_time_stddev = F64Seconds(std::sqrt(val));
334+
}
335+
sample(LLStatViewer::FRAMETIME_STDDEV, frame_time_stddev);
336+
337+
if (mFrameTimes.size() > 0)
338+
{
339+
size_t n = mFrameTimes.size();
340+
size_t ninety_ninth_index = (size_t)(n * 0.99);
341+
size_t ninety_fifth_index = (size_t)(n * 0.95);
342+
if (ninety_ninth_index < n)
343+
{
344+
ninety_ninth_percentile = mFrameTimes[ninety_ninth_index];
345+
}
346+
if (ninety_fifth_index < n)
347+
{
348+
ninety_fifth_percentile = mFrameTimes[ninety_fifth_index];
349+
}
350+
}
351+
sample(LLStatViewer::FRAMETIME_99TH, ninety_ninth_percentile);
352+
sample(LLStatViewer::FRAMETIME_95TH, ninety_fifth_percentile);
276353

354+
ninety_ninth_percentile = F64Seconds(0);
355+
ninety_fifth_percentile = F64Seconds(0);
356+
frame_time_stddev = F64Seconds(0);
357+
if (mFrameTimesJitter.size() > 1)
358+
{
359+
F64Seconds mean(0);
360+
for (const auto& v : mFrameTimesJitter)
361+
{
362+
mean += v;
363+
}
364+
mean /= (F64)mFrameTimesJitter.size();
365+
366+
F64Seconds variance(0);
367+
for (const auto& v : mFrameTimesJitter)
368+
{
369+
F64Seconds diff = v - mean;
370+
F64 diff_squared;
371+
diff.value(diff_squared);
372+
diff_squared = std::pow(diff_squared, 2);
373+
variance += F64Seconds(diff_squared);
374+
}
375+
variance /= (F64)(mFrameTimesJitter.size() - 1); // Use sample variance (n-1)
376+
F64 val;
377+
variance.value(val);
378+
frame_time_stddev = F64Seconds(std::sqrt(val));
379+
}
380+
sample(LLStatViewer::FRAMETIME_JITTER_STDDEV, frame_time_stddev);
381+
382+
if (mFrameTimesJitter.size() > 0)
383+
{
384+
size_t n = mFrameTimesJitter.size();
385+
size_t ninety_ninth_index = (size_t)(n * 0.99);
386+
size_t ninety_fifth_index = (size_t)(n * 0.95);
387+
if (ninety_ninth_index < n)
388+
{
389+
ninety_ninth_percentile = mFrameTimesJitter[ninety_ninth_index];
390+
}
391+
if (ninety_fifth_index < n)
392+
{
393+
ninety_fifth_percentile = mFrameTimesJitter[ninety_fifth_index];
394+
}
395+
}
396+
sample(LLStatViewer::FRAMETIME_JITTER_99TH, ninety_ninth_percentile);
397+
sample(LLStatViewer::FRAMETIME_JITTER_95TH, ninety_fifth_percentile);
398+
399+
mFrameTimes.clear();
400+
mFrameTimesJitter.clear();
401+
mLastFrameTimeSample = F64Seconds(0);
402+
}
403+
}
277404
mLastTimeDiff = time_diff;
278405
}
279406

indra/newview/llviewerstats.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,13 @@ class LLViewerStats : public LLSingleton<LLViewerStats>
275275
LLTrace::Recording mRecording;
276276

277277
F64Seconds mLastTimeDiff; // used for time stat updates
278+
F64Seconds mTotalFrametimeJitter;
279+
280+
U32 mFrameJitterEvents;
281+
282+
F64Seconds mLastFrameTimeSample; // used for frame time stats
283+
std::vector<F64Seconds> mFrameTimes; // used for frame time stats
284+
std::vector<F64Seconds> mFrameTimesJitter; // used for frame time jitter stats
278285
};
279286

280287
static const F32 SEND_STATS_PERIOD = 300.0f;

indra/newview/skins/default/xui/en/floater_stats.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,38 @@
5454
label="jitter"
5555
decimal_digits="1"
5656
stat="frametimejitter"/>
57+
<stat_bar name="framet_cumulative"
58+
label="jitter cumulative"
59+
decimal_digits="1"
60+
stat="frametimejitcumulative"/>
61+
<stat_bar name="framet_jitter_99th"
62+
label="jitter 99th percentile"
63+
decimal_digits="1"
64+
stat="frametimejitter99"/>
65+
<stat_bar name="framet_jitter_95th"
66+
label="jitter 95th percentile"
67+
decimal_digits="1"
68+
stat="frametimejitter95"/>
69+
<stat_bar name="framet_jitter_stddev"
70+
label="frametime jitter standard deviation"
71+
decimal_digits="1"
72+
stat="frametimejitterstddev"/>
73+
<stat_bar name="framet_99th"
74+
label="frametime 99th percentile"
75+
decimal_digits="1"
76+
stat="frametime99"/>
77+
<stat_bar name="framet_95th"
78+
label="frametime 95th percentile"
79+
decimal_digits="1"
80+
stat="frametime95"/>
81+
<stat_bar name="framet_stddev"
82+
label="frametime standard deviation"
83+
decimal_digits="1"
84+
stat="frametimestddev"/>
85+
<stat_bar name="framet_events"
86+
label="frametime events"
87+
decimal_digits="1"
88+
stat="frametimeevents"/>
5789
<stat_bar name="bandwidth"
5890
label="UDP Data Received"
5991
stat="activemessagedatareceived"

0 commit comments

Comments
 (0)