Add performance metrics for worker and render ticks

- Introduced new metrics in ClientGameRunner to track worker simulation ticks and render tick calls per second.
- Updated TickMetricsEvent to include these new metrics.
- Enhanced PerformanceOverlay to display worker and render ticks per second, improving performance monitoring capabilities.
- Adjusted minimum FPS in GameRenderer
This commit is contained in:
scamiv
2025-11-25 19:21:33 +01:00
parent 391f19d061
commit 2f2a12eefa
4 changed files with 56 additions and 2 deletions
+24
View File
@@ -233,6 +233,9 @@ export class ClientGameRunner {
private backlogTurns: number = 0;
private backlogGrowing: boolean = false;
private lastRenderedTick: number = 0;
private workerTicksSinceSample: number = 0;
private renderTicksSinceSample: number = 0;
private metricsSampleStart: number = 0;
private pendingUpdates: GameUpdateViewData[] = [];
private pendingStart = 0;
@@ -495,6 +498,7 @@ export class ClientGameRunner {
while (this.pendingStart < this.pendingUpdates.length) {
const gu = this.pendingUpdates[this.pendingStart++];
processedCount++;
this.workerTicksSinceSample++;
batch.push(gu);
this.transport.turnComplete();
@@ -545,6 +549,24 @@ export class ClientGameRunner {
: lastTick - this.lastRenderedTick;
this.lastRenderedTick = lastTick;
this.renderTicksSinceSample++;
let workerTicksPerSecond: number | undefined;
let renderTicksPerSecond: number | undefined;
const now = performance.now();
if (this.metricsSampleStart === 0) {
this.metricsSampleStart = now;
} else {
const elapsedSeconds = (now - this.metricsSampleStart) / 1000;
if (elapsedSeconds > 0) {
workerTicksPerSecond = this.workerTicksSinceSample / elapsedSeconds;
renderTicksPerSecond = this.renderTicksSinceSample / elapsedSeconds;
}
this.metricsSampleStart = now;
this.workerTicksSinceSample = 0;
this.renderTicksSinceSample = 0;
}
this.renderer.tick();
this.eventBus.emit(
new TickMetricsEvent(
@@ -552,6 +574,8 @@ export class ClientGameRunner {
this.currentTickDelay,
this.backlogTurns,
ticksPerRender,
workerTicksPerSecond,
renderTicksPerSecond,
),
);
+5 -1
View File
@@ -131,8 +131,12 @@ export class TickMetricsEvent implements GameEvent {
public readonly tickDelay?: number,
// Number of turns the client is behind the server (if known)
public readonly backlogTurns?: number,
// Number of ticks applied since last render
// Number of simulation ticks applied since last render
public readonly ticksPerRender?: number,
// Approximate worker simulation ticks per second
public readonly workerTicksPerSecond?: number,
// Approximate render tick() calls per second
public readonly renderTicksPerSecond?: number,
) {}
}
+1 -1
View File
@@ -362,7 +362,7 @@ export class GameRenderer {
if (this.backlogTurns > 0) {
const BASE_FPS = 60;
const MIN_FPS = 20;
const MIN_FPS = 10;
const BACKLOG_MAX_TURNS = 50;
const scale = Math.min(1, this.backlogTurns / BACKLOG_MAX_TURNS);
@@ -234,6 +234,8 @@ export class PerformanceOverlay extends LitElement implements Layer {
event.tickDelay,
event.backlogTurns,
event.ticksPerRender,
event.workerTicksPerSecond,
event.renderTicksPerSecond,
);
});
}
@@ -429,11 +431,19 @@ export class PerformanceOverlay extends LitElement implements Layer {
@state()
private ticksPerRender: number = 0;
@state()
private workerTicksPerSecond: number = 0;
@state()
private renderTicksPerSecond: number = 0;
updateTickMetrics(
tickExecutionDuration?: number,
tickDelay?: number,
backlogTurns?: number,
ticksPerRender?: number,
workerTicksPerSecond?: number,
renderTicksPerSecond?: number,
) {
if (!this.isVisible || !this.userSettings.performanceOverlay()) return;
@@ -479,6 +489,14 @@ export class PerformanceOverlay extends LitElement implements Layer {
this.ticksPerRender = ticksPerRender;
}
if (workerTicksPerSecond !== undefined) {
this.workerTicksPerSecond = workerTicksPerSecond;
}
if (renderTicksPerSecond !== undefined) {
this.renderTicksPerSecond = renderTicksPerSecond;
}
this.requestUpdate();
}
@@ -624,6 +642,14 @@ export class PerformanceOverlay extends LitElement implements Layer {
<span>${this.tickDelayAvg.toFixed(2)}ms</span>
(max: <span>${this.tickDelayMax}ms</span>)
</div>
<div class="performance-line">
Worker ticks/s:
<span>${this.workerTicksPerSecond.toFixed(1)}</span>
</div>
<div class="performance-line">
Render ticks/s:
<span>${this.renderTicksPerSecond.toFixed(1)}</span>
</div>
<div class="performance-line">
Ticks per render:
<span>${this.ticksPerRender}</span>