@@ -273,6 +273,38 @@ void LLViewerStats::resetStats()
273
273
getRecording ().reset ();
274
274
}
275
275
276
+ // Helper for calculating Nth percentile with linear interpolation
277
+ template <typename T>
278
+ T calcPercentile (const std::vector<T>& sorted, double percent)
279
+ {
280
+ if (sorted.empty ())
281
+ return T (0 );
282
+ double idx = percent * (sorted.size () - 1 );
283
+ size_t idx_below = static_cast <size_t >(std::floor (idx));
284
+ size_t idx_above = static_cast <size_t >(std::ceil (idx));
285
+ if (idx_below == idx_above)
286
+ return sorted[idx_below];
287
+ double weight_above = idx - idx_below;
288
+ return sorted[idx_below] * (1.0 - weight_above) + sorted[idx_above] * weight_above;
289
+ }
290
+
291
+ template <typename T>
292
+ T calcStddev (const std::vector<T>& values)
293
+ {
294
+ if (values.size () < 2 )
295
+ return T (0 );
296
+ double sum = 0 , sq_sum = 0 ;
297
+ for (const auto & v : values)
298
+ {
299
+ double d = v.value ();
300
+ sum += d;
301
+ sq_sum += d * d;
302
+ }
303
+ double mean = sum / values.size ();
304
+ double variance = (sq_sum / values.size ()) - (mean * mean);
305
+ return T (std::sqrt (variance));
306
+ }
307
+
276
308
void LLViewerStats::updateFrameStats (const F64Seconds time_diff)
277
309
{
278
310
if (gFrameCount && mLastTimeDiff > (F64Seconds)0.0 )
@@ -300,99 +332,23 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff)
300
332
301
333
if (mLastFrameTimeSample >= frameTimeSampleSeconds ())
302
334
{
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
335
std::sort (mFrameTimes .begin (), mFrameTimes .end ());
306
336
std::sort (mFrameTimesJitter .begin (), mFrameTimesJitter .end ());
307
- F64Seconds ninety_ninth_percentile;
308
- F64Seconds ninety_fifth_percentile;
309
337
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
- }
338
+ // Use new helpers for calculations
339
+ F64Seconds frame_time_stddev = calcStddev (mFrameTimes );
335
340
sample (LLStatViewer::FRAMETIME_STDDEV, frame_time_stddev);
336
341
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
- }
342
+ F64Seconds ninety_ninth_percentile = calcPercentile (mFrameTimes , 0.99 );
343
+ F64Seconds ninety_fifth_percentile = calcPercentile (mFrameTimes , 0.95 );
351
344
sample (LLStatViewer::FRAMETIME_99TH, ninety_ninth_percentile);
352
345
sample (LLStatViewer::FRAMETIME_95TH, ninety_fifth_percentile);
353
346
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
- }
347
+ frame_time_stddev = calcStddev (mFrameTimesJitter );
380
348
sample (LLStatViewer::FRAMETIME_JITTER_STDDEV, frame_time_stddev);
381
349
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
- }
350
+ ninety_ninth_percentile = calcPercentile (mFrameTimesJitter , 0.99 );
351
+ ninety_fifth_percentile = calcPercentile (mFrameTimesJitter , 0.95 );
396
352
sample (LLStatViewer::FRAMETIME_JITTER_99TH, ninety_ninth_percentile);
397
353
sample (LLStatViewer::FRAMETIME_JITTER_95TH, ninety_fifth_percentile);
398
354
0 commit comments