/ utils / fpsTracker.ts
fpsTracker.ts
 1  export type FpsMetrics = {
 2    averageFps: number
 3    low1PctFps: number
 4  }
 5  
 6  export class FpsTracker {
 7    private frameDurations: number[] = []
 8    private firstRenderTime: number | undefined
 9    private lastRenderTime: number | undefined
10  
11    record(durationMs: number): void {
12      const now = performance.now()
13      if (this.firstRenderTime === undefined) {
14        this.firstRenderTime = now
15      }
16      this.lastRenderTime = now
17      this.frameDurations.push(durationMs)
18    }
19  
20    getMetrics(): FpsMetrics | undefined {
21      if (
22        this.frameDurations.length === 0 ||
23        this.firstRenderTime === undefined ||
24        this.lastRenderTime === undefined
25      ) {
26        return undefined
27      }
28  
29      const totalTimeMs = this.lastRenderTime - this.firstRenderTime
30      if (totalTimeMs <= 0) {
31        return undefined
32      }
33  
34      const totalFrames = this.frameDurations.length
35      const averageFps = totalFrames / (totalTimeMs / 1000)
36  
37      const sorted = this.frameDurations.slice().sort((a, b) => b - a)
38      const p99Index = Math.max(0, Math.ceil(sorted.length * 0.01) - 1)
39      const p99FrameTimeMs = sorted[p99Index]!
40      const low1PctFps = p99FrameTimeMs > 0 ? 1000 / p99FrameTimeMs : 0
41  
42      return {
43        averageFps: Math.round(averageFps * 100) / 100,
44        low1PctFps: Math.round(low1PctFps * 100) / 100,
45      }
46    }
47  }