140 lines
3.5 KiB
TypeScript
140 lines
3.5 KiB
TypeScript
/**
|
|
* Performance Monitoring
|
|
*/
|
|
|
|
import * as THREE from 'three'
|
|
|
|
export interface PerformanceMetrics {
|
|
fps: number
|
|
frameTime: number
|
|
drawCalls: number
|
|
triangles: number
|
|
geometries: number
|
|
textures: number
|
|
programs: number
|
|
memory: {
|
|
geometries: number
|
|
textures: number
|
|
total: number
|
|
}
|
|
renderTime: number
|
|
gpuTime: number
|
|
}
|
|
|
|
export class PerformanceMonitor {
|
|
private static instance: PerformanceMonitor
|
|
private metrics: PerformanceMetrics = {
|
|
fps: 60,
|
|
frameTime: 16.67,
|
|
drawCalls: 0,
|
|
triangles: 0,
|
|
geometries: 0,
|
|
textures: 0,
|
|
programs: 0,
|
|
memory: { geometries: 0, textures: 0, total: 0 },
|
|
renderTime: 0,
|
|
gpuTime: 0
|
|
}
|
|
|
|
private fpsHistory: number[] = []
|
|
private lastTime: number = performance.now()
|
|
private frames: number = 0
|
|
private callbacks: Set<(metrics: PerformanceMetrics) => void> = new Set()
|
|
|
|
private constructor() {
|
|
setInterval(() => {
|
|
this.updateMetrics()
|
|
this.notifyCallbacks()
|
|
}, 1000)
|
|
}
|
|
|
|
static getInstance(): PerformanceMonitor {
|
|
if (!PerformanceMonitor.instance) {
|
|
PerformanceMonitor.instance = new PerformanceMonitor()
|
|
}
|
|
return PerformanceMonitor.instance
|
|
}
|
|
|
|
private updateMetrics(): void {
|
|
const currentTime = performance.now()
|
|
const deltaTime = currentTime - this.lastTime
|
|
|
|
if (deltaTime >= 1000) {
|
|
this.metrics.fps = Math.round((this.frames * 1000) / deltaTime)
|
|
this.metrics.frameTime = deltaTime / this.frames
|
|
|
|
this.fpsHistory.push(this.metrics.fps)
|
|
if (this.fpsHistory.length > 60) this.fpsHistory.shift()
|
|
|
|
this.frames = 0
|
|
this.lastTime = currentTime
|
|
}
|
|
}
|
|
|
|
updateRendererMetrics(renderer: THREE.WebGLRenderer): void {
|
|
const info = renderer.info
|
|
this.metrics.drawCalls = info.render.calls
|
|
this.metrics.triangles = info.render.triangles
|
|
this.metrics.geometries = info.memory.geometries
|
|
this.metrics.textures = info.memory.textures
|
|
this.metrics.programs = info.programs?.length || 0
|
|
this.frames++
|
|
}
|
|
|
|
getMetrics(): PerformanceMetrics {
|
|
return { ...this.metrics }
|
|
}
|
|
|
|
getAverageFPS(): number {
|
|
if (this.fpsHistory.length === 0) return 0
|
|
return this.fpsHistory.reduce((a, b) => a + b, 0) / this.fpsHistory.length
|
|
}
|
|
|
|
getFPSVariance(): number {
|
|
if (this.fpsHistory.length === 0) return 0
|
|
const avg = this.getAverageFPS()
|
|
const variance = this.fpsHistory.reduce((sum, fps) => sum + Math.pow(fps - avg, 2), 0) / this.fpsHistory.length
|
|
return Math.sqrt(variance)
|
|
}
|
|
|
|
getPerformanceGrade(): 'A' | 'B' | 'C' | 'D' | 'F' {
|
|
const avgFPS = this.getAverageFPS()
|
|
if (avgFPS >= 60) return 'A'
|
|
if (avgFPS >= 45) return 'B'
|
|
if (avgFPS >= 30) return 'C'
|
|
if (avgFPS >= 20) return 'D'
|
|
return 'F'
|
|
}
|
|
|
|
generateReport() {
|
|
return {
|
|
grade: this.getPerformanceGrade(),
|
|
avgFPS: this.getAverageFPS(),
|
|
variance: this.getFPSVariance(),
|
|
recommendations: []
|
|
}
|
|
}
|
|
|
|
subscribe(callback: (metrics: PerformanceMetrics) => void): () => void {
|
|
this.callbacks.add(callback)
|
|
return () => this.callbacks.delete(callback)
|
|
}
|
|
|
|
private notifyCallbacks(): void {
|
|
this.callbacks.forEach(cb => cb(this.metrics))
|
|
}
|
|
|
|
reset(): void {
|
|
this.fpsHistory = []
|
|
this.frames = 0
|
|
this.lastTime = performance.now()
|
|
}
|
|
|
|
getCurrentPreset() {
|
|
return {
|
|
name: this.metrics.fps >= 60 ? 'ultra' : this.metrics.fps >= 45 ? 'high' : this.metrics.fps >= 30 ? 'medium' : 'low',
|
|
minFPS: this.metrics.fps
|
|
}
|
|
}
|
|
}
|