diff --git a/packages/engine-render/src/basics/__tests__/performance-monitor.spec.ts b/packages/engine-render/src/basics/__tests__/performance-monitor.spec.ts index 131b713c08..43616ea6a3 100644 --- a/packages/engine-render/src/basics/__tests__/performance-monitor.spec.ts +++ b/packages/engine-render/src/basics/__tests__/performance-monitor.spec.ts @@ -97,4 +97,15 @@ describe('performance monitor', () => { expect(average.averageFrameTime).toBeCloseTo(16.67, 2); expect(average.variance).toBe(0); }); + + it('removes only one minimum and maximum from duplicate samples', () => { + const average = new RollingAverage(3); + + for (const frameTime of [10, 10, 20]) { + average.addFrameTime(frameTime); + average.calcAverageFrameTime(); + } + + expect(average.averageFrameTime).toBe(10); + }); }); diff --git a/packages/engine-render/src/basics/performance-monitor.ts b/packages/engine-render/src/basics/performance-monitor.ts index 6399d35dd3..12aedc6697 100644 --- a/packages/engine-render/src/basics/performance-monitor.ts +++ b/packages/engine-render/src/basics/performance-monitor.ts @@ -265,11 +265,17 @@ export class RollingAverage { this._sampleCount++; } - // Remove one maximum and one minimum to ensure the accuracy of the average value. - const min = Math.min(...this._samples); - const max = Math.min(...this._samples); - const filteredData = this._samples.filter((v) => v !== max && v !== min); - this.averageFrameTime = filteredData.reduce((sum, value) => sum + value, 0) / filteredData.length; + // Once the window is full, exclude one minimum and maximum to reduce outlier bias. + const shouldTrimExtremes = this.isSaturated() && this._sampleCount > 2; + const sampleSum = this._samples.reduce((sum, value) => sum + value, 0); + + if (shouldTrimExtremes) { + const min = Math.min(...this._samples); + const max = Math.max(...this._samples); + this.averageFrameTime = (sampleSum - min - max) / (this._sampleCount - 2); + } else { + this.averageFrameTime = sampleSum / this._sampleCount; + } // add new value to mean delta = frameDuration - this.averageFrameTime;