orbit-studio / src /modules /util /CesiumPerformanceStats.ts
moncefem's picture
Deploy Orbit Studio propagator
9f21d0a
Raw
History Blame Contribute Delete
2.72 kB
import { getTimestamp } from "@cesium/engine";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Scene = any;
const fmt = (n: number): string => n.toFixed(2).padStart(8);
export interface CesiumPerformanceStatsResult {
avgFps: number;
avgFrameTime: number;
worstFrameTime: number;
}
// Mean and worst frame time over a sample period.
export class CesiumPerformanceStats {
scene: Scene;
sampleCount = 60;
idx = 0;
postRenderTimes: number[] = [];
discardNext = true;
avgFps = 0;
avgFrameTime = 0;
worstFrameTime = 0;
constructor(scene: Scene, logContinuously = false) {
this.scene = scene;
// Render-on-demand skips frames when nothing moved, which would make the gap
// between postRender events a measure of how idle the loop is rather than of
// what a frame costs.
this.scene.requestRenderMode = false;
this.scene.preUpdate.addEventListener(() => {
performance.mark("preUpdate");
});
this.scene.postRender.addEventListener(() => {
performance.mark("postRender");
this.postRenderTimes[this.idx] = getTimestamp();
this.idx = (this.idx + 1) % this.sampleCount;
if (this.idx === 0) {
if (this.discardNext) {
this.discardNext = false;
} else {
this.calculateStats();
if (logContinuously) {
console.log(this.formatStats());
}
}
}
performance.measure("SceneRender", "preUpdate", "postRender");
});
}
calculateStats(): void {
this.worstFrameTime = 0;
for (let i = 0; i < this.sampleCount - 1; i += 1) {
const a = this.postRenderTimes[i + 1];
const b = this.postRenderTimes[i];
if (a === undefined || b === undefined) continue;
const frametime = a - b;
if (frametime > this.worstFrameTime) {
this.worstFrameTime = frametime;
}
}
const last = this.postRenderTimes[this.sampleCount - 1];
const first = this.postRenderTimes[0];
if (last === undefined || first === undefined) return;
const duration = last - first;
this.avgFps = this.sampleCount / (duration / 1000);
this.avgFrameTime = duration / this.sampleCount;
}
reset(discardNext = true): void {
this.idx = 0;
this.discardNext = discardNext;
this.avgFps = 0;
this.avgFrameTime = 0;
this.worstFrameTime = 0;
}
getStats(): CesiumPerformanceStatsResult {
return {
avgFps: this.avgFps,
avgFrameTime: this.avgFrameTime,
worstFrameTime: this.worstFrameTime,
};
}
formatStats(): string {
return `Avg FPS: ${fmt(this.avgFps)}; Avg Frametime: ${fmt(this.avgFrameTime)}; Worst Frametime: ${fmt(this.worstFrameTime)};`;
}
}