diff options
author | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2025-06-27 15:41:58 -0400 |
---|---|---|
committer | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2025-06-27 15:41:58 -0400 |
commit | 15574431354e55059c4514fa51a7c78b90ed8b6e (patch) | |
tree | e76f6a4adcce690b8fb83c7b355ceecf1bfa2097 /indra | |
parent | feb4494365e019efd68d6881e4ff63e939a01264 (diff) |
First pass at adding expanded frametiming stats to the viewer.
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/app_settings/settings.xml | 22 | ||||
-rw-r--r-- | indra/newview/llviewerstats.cpp | 129 | ||||
-rw-r--r-- | indra/newview/llviewerstats.h | 7 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_stats.xml | 32 |
4 files changed, 188 insertions, 2 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8cfe4f3d97..c4cae5748e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11488,6 +11488,28 @@ <key>Value</key> <string>fss.txt</string> </map> + <key>StatsFrametimeSampleSeconds</key> + <map> + <key>Comment</key> + <string>The number of seconds to sample extended frametime data (percentiles, stddev).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>5</integer> + </map> + <key>StatsFrametimeEventThreshold</key> + <map> + <key>Comment</key> + <string>The percentage that the frametime difference must exceed in order to register a frametime event. 0.1 = 10%, 0.25 = 25%, etc.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.1</real> + </map> <key>SystemLanguage</key> <map> <key>Comment</key> diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 73aabf49d1..e5a347ecdd 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -220,7 +220,16 @@ SimMeasurement<F64Megabytes > SIM_PHYSICS_MEM("physicsmemoryallocated", "", LL LLTrace::SampleStatHandle<F64Milliseconds > FRAMETIME_JITTER("frametimejitter", "Average delta between successive frame times"), FRAMETIME("frametime", "Measured frame time"), - SIM_PING("simpingstat"); + SIM_PING("simpingstat"), + FRAMETIME_JITTER_99TH("frametimejitter99", "99th percentile of frametime jitter over the last 5 seconds."), + FRAMETIME_JITTER_95TH("frametimejitter95", "99th percentile of frametime jitter over the last 5 seconds."), + FRAMETIME_99TH("frametime99", "99th percentile of frametime over the last 5 seconds."), + FRAMETIME_95TH("frametime95", "99th percentile of frametime over the last 5 seconds."), + FRAMETIME_JITTER_CUMULATIVE("frametimejitcumulative", "Cumulative frametime jitter over the session."), + FRAMETIME_JITTER_STDDEV("frametimejitterstddev", "Standard deviation of frametime jitter in a 5 second period."), + FRAMETIME_STDDEV("frametimestddev", "Standard deviation of frametime in a 5 second period."); + +LLTrace::SampleStatHandle<U32> FRAMETIME_JITTER_EVENTS("frametimeevents", "Number of frametime events in the session. Applies when jitter exceeds 10% of the previous frame."); LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Meters> > AGENT_POSITION_SNAP("agentpositionsnap", "agent position corrections"); @@ -272,8 +281,124 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff) // old stats that were never really used F64Seconds jit = (F64Seconds)std::fabs((mLastTimeDiff - time_diff)); sample(LLStatViewer::FRAMETIME_JITTER, jit); - } + mTotalFrametimeJitter += jit; + sample(LLStatViewer::FRAMETIME_JITTER_CUMULATIVE, mTotalFrametimeJitter); + + static LLCachedControl<F32> frameTimeEventThreshold(gSavedSettings, "StatsFrametimeEventThreshold", 0.1f); + + if (time_diff - mLastTimeDiff > mLastTimeDiff * frameTimeEventThreshold()) + { + sample(LLStatViewer::FRAMETIME_JITTER_EVENTS, mFrameJitterEvents++); + } + + mFrameTimes.push_back(time_diff); + mFrameTimesJitter.push_back(jit); + + mLastFrameTimeSample += time_diff; + + static LLCachedControl<S32> frameTimeSampleSeconds(gSavedSettings, "StatsFrametimeSampleSeconds", 5); + + if (mLastFrameTimeSample >= frameTimeSampleSeconds()) + { + // @TODO: This needs to be de-duped and moved into specific functions. + // If we have more than 5 seconds of frame time samples, calculate the stddev, 99th percentile, and 95th percentile. + std::sort(mFrameTimes.begin(), mFrameTimes.end()); + std::sort(mFrameTimesJitter.begin(), mFrameTimesJitter.end()); + F64Seconds ninety_ninth_percentile; + F64Seconds ninety_fifth_percentile; + + // Calculate standard deviation of mFrameTimes + F64Seconds frame_time_stddev(0); + if (mFrameTimes.size() > 1) + { + F64Seconds mean(0); + for (const auto& v : mFrameTimes) + { + mean += v; + } + mean /= (F64)mFrameTimes.size(); + + F64Seconds variance(0); + for (const auto& v : mFrameTimes) + { + F64Seconds diff = v - mean; + F64 diff_squared; + diff.value(diff_squared); + diff_squared = std::pow(diff_squared, 2); + variance += F64Seconds(diff_squared); + } + variance /= (F64)(mFrameTimes.size() - 1); // Use sample variance (n-1) + F64 val; + variance.value(val); + frame_time_stddev = F64Seconds(std::sqrt(val)); + } + sample(LLStatViewer::FRAMETIME_STDDEV, frame_time_stddev); + + if (mFrameTimes.size() > 0) + { + size_t n = mFrameTimes.size(); + size_t ninety_ninth_index = (size_t)(n * 0.99); + size_t ninety_fifth_index = (size_t)(n * 0.95); + if (ninety_ninth_index < n) + { + ninety_ninth_percentile = mFrameTimes[ninety_ninth_index]; + } + if (ninety_fifth_index < n) + { + ninety_fifth_percentile = mFrameTimes[ninety_fifth_index]; + } + } + + sample(LLStatViewer::FRAMETIME_99TH, ninety_ninth_percentile); + sample(LLStatViewer::FRAMETIME_95TH, ninety_fifth_percentile); + if (mFrameTimesJitter.size() > 1) + { + F64Seconds mean(0); + for (const auto& v : mFrameTimesJitter) + { + mean += v; + } + mean /= (F64)mFrameTimesJitter.size(); + + F64Seconds variance(0); + for (const auto& v : mFrameTimesJitter) + { + F64Seconds diff = v - mean; + F64 diff_squared; + diff.value(diff_squared); + diff_squared = std::pow(diff_squared, 2); + variance += F64Seconds(diff_squared); + } + variance /= (F64)(mFrameTimesJitter.size() - 1); // Use sample variance (n-1) + F64 val; + variance.value(val); + frame_time_stddev = F64Seconds(std::sqrt(val)); + } + sample(LLStatViewer::FRAMETIME_JITTER_STDDEV, frame_time_stddev); + + if (mFrameTimesJitter.size() > 0) + { + size_t n = mFrameTimesJitter.size(); + size_t ninety_ninth_index = (size_t)(n * 0.99); + size_t ninety_fifth_index = (size_t)(n * 0.95); + if (ninety_ninth_index < n) + { + ninety_ninth_percentile = mFrameTimesJitter[ninety_ninth_index]; + } + if (ninety_fifth_index < n) + { + ninety_fifth_percentile = mFrameTimesJitter[ninety_fifth_index]; + } + } + sample(LLStatViewer::FRAMETIME_JITTER_99TH, ninety_ninth_percentile); + sample(LLStatViewer::FRAMETIME_JITTER_95TH, ninety_fifth_percentile); + + mFrameTimes.clear(); + mFrameTimesJitter.clear(); + mLastFrameTimeSample = F64Seconds(0); + } + } mLastTimeDiff = time_diff; } diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 8aed1c537e..1d84ab9fbc 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -275,6 +275,13 @@ private: LLTrace::Recording mRecording; F64Seconds mLastTimeDiff; // used for time stat updates + F64Seconds mTotalFrametimeJitter; + + U32 mFrameJitterEvents; + + F64Seconds mLastFrameTimeSample; // used for frame time stats + std::vector<F64Seconds> mFrameTimes; // used for frame time stats + std::vector<F64Seconds> mFrameTimesJitter; // used for frame time jitter stats }; static const F32 SEND_STATS_PERIOD = 300.0f; diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index 6633e25099..84252fe32c 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -54,6 +54,38 @@ label="jitter" decimal_digits="1" stat="frametimejitter"/> + <stat_bar name="framet_cumulative" + label="jitter cumulative" + decimal_digits="1" + stat="frametimejitcumulative"/> + <stat_bar name="framet_jitter_99th" + label="jitter 99th percentile" + decimal_digits="1" + stat="frametimejitter99"/> + <stat_bar name="framet_jitter_95th" + label="jitter 95th percentile" + decimal_digits="1" + stat="frametimejitter95"/> + <stat_bar name="framet_jitter_stddev" + label="frametime jitter standard deviation" + decimal_digits="1" + stat="frametimejitterstddev"/> + <stat_bar name="framet_99th" + label="frametime 99th percentile" + decimal_digits="1" + stat="frametime99"/> + <stat_bar name="framet_95th" + label="frametime 95th percentile" + decimal_digits="1" + stat="frametime95"/> + <stat_bar name="framet_stddev" + label="frametime standard deviation" + decimal_digits="1" + stat="frametimestddev"/> + <stat_bar name="framet_events" + label="frametime events" + decimal_digits="1" + stat="frametimeevents"/> <stat_bar name="bandwidth" label="UDP Data Received" stat="activemessagedatareceived" |