mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-08-07 19:21:30 +00:00
add more stats to perf overlay
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
|||||||
drainTileUpdates,
|
drainTileUpdates,
|
||||||
SharedTileRingBuffers,
|
SharedTileRingBuffers,
|
||||||
SharedTileRingViews,
|
SharedTileRingViews,
|
||||||
|
TILE_RING_HEADER_OVERFLOW,
|
||||||
} from "../core/worker/SharedTileRing";
|
} from "../core/worker/SharedTileRing";
|
||||||
import { WorkerClient } from "../core/worker/WorkerClient";
|
import { WorkerClient } from "../core/worker/WorkerClient";
|
||||||
import {
|
import {
|
||||||
@@ -561,7 +562,8 @@ export class ClientGameRunner {
|
|||||||
batch.length > 0 &&
|
batch.length > 0 &&
|
||||||
lastTick !== undefined
|
lastTick !== undefined
|
||||||
) {
|
) {
|
||||||
const combinedGu = this.mergeGameUpdates(batch);
|
const { gameUpdate: combinedGu, tileMetrics } =
|
||||||
|
this.mergeGameUpdates(batch);
|
||||||
if (combinedGu) {
|
if (combinedGu) {
|
||||||
this.gameView.update(combinedGu);
|
this.gameView.update(combinedGu);
|
||||||
}
|
}
|
||||||
@@ -599,6 +601,10 @@ export class ClientGameRunner {
|
|||||||
ticksPerRender,
|
ticksPerRender,
|
||||||
workerTicksPerSecond,
|
workerTicksPerSecond,
|
||||||
renderTicksPerSecond,
|
renderTicksPerSecond,
|
||||||
|
tileMetrics.count,
|
||||||
|
tileMetrics.utilization,
|
||||||
|
tileMetrics.overflow,
|
||||||
|
tileMetrics.drainTime,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -616,9 +622,15 @@ export class ClientGameRunner {
|
|||||||
requestAnimationFrame(processFrame);
|
requestAnimationFrame(processFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
private mergeGameUpdates(
|
private mergeGameUpdates(batch: GameUpdateViewData[]): {
|
||||||
batch: GameUpdateViewData[],
|
gameUpdate: GameUpdateViewData | null;
|
||||||
): GameUpdateViewData | null {
|
tileMetrics: {
|
||||||
|
count: number;
|
||||||
|
utilization: number;
|
||||||
|
overflow: number;
|
||||||
|
drainTime: number;
|
||||||
|
};
|
||||||
|
} {
|
||||||
if (batch.length === 0) {
|
if (batch.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -644,31 +656,60 @@ export class ClientGameRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tileMetrics = {
|
||||||
|
count: 0,
|
||||||
|
utilization: 0,
|
||||||
|
overflow: 0,
|
||||||
|
drainTime: 0,
|
||||||
|
};
|
||||||
|
|
||||||
if (this.tileRingViews) {
|
if (this.tileRingViews) {
|
||||||
const MAX_TILE_UPDATES_PER_RENDER = 100000;
|
const MAX_TILE_UPDATES_PER_RENDER = 100000;
|
||||||
const tileRefs: TileRef[] = [];
|
const tileRefs: TileRef[] = [];
|
||||||
|
const drainStart = performance.now();
|
||||||
drainTileUpdates(
|
drainTileUpdates(
|
||||||
this.tileRingViews,
|
this.tileRingViews,
|
||||||
MAX_TILE_UPDATES_PER_RENDER,
|
MAX_TILE_UPDATES_PER_RENDER,
|
||||||
tileRefs,
|
tileRefs,
|
||||||
);
|
);
|
||||||
|
const drainTime = performance.now() - drainStart;
|
||||||
|
|
||||||
|
// Calculate ring buffer utilization and overflow
|
||||||
|
const TILE_RING_CAPACITY = 262144;
|
||||||
|
const utilization = (tileRefs.length / TILE_RING_CAPACITY) * 100;
|
||||||
|
const overflow = Atomics.load(
|
||||||
|
this.tileRingViews.header,
|
||||||
|
TILE_RING_HEADER_OVERFLOW,
|
||||||
|
);
|
||||||
|
|
||||||
|
tileMetrics = {
|
||||||
|
count: tileRefs.length,
|
||||||
|
utilization,
|
||||||
|
overflow,
|
||||||
|
drainTime,
|
||||||
|
};
|
||||||
|
|
||||||
for (const ref of tileRefs) {
|
for (const ref of tileRefs) {
|
||||||
combinedPackedTileUpdates.push(BigInt(ref));
|
combinedPackedTileUpdates.push(BigInt(ref));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Non-SAB mode: count tile updates from batch
|
||||||
|
let totalTileUpdates = 0;
|
||||||
for (const gu of batch) {
|
for (const gu of batch) {
|
||||||
gu.packedTileUpdates.forEach((tu) => {
|
totalTileUpdates += gu.packedTileUpdates.length;
|
||||||
combinedPackedTileUpdates.push(tu);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
tileMetrics.count = totalTileUpdates;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tick: last.tick,
|
gameUpdate: {
|
||||||
updates: combinedUpdates,
|
tick: last.tick,
|
||||||
packedTileUpdates: new BigUint64Array(combinedPackedTileUpdates),
|
updates: combinedUpdates,
|
||||||
playerNameViewData: last.playerNameViewData,
|
packedTileUpdates: new BigUint64Array(combinedPackedTileUpdates),
|
||||||
tickExecutionDuration: last.tickExecutionDuration,
|
playerNameViewData: last.playerNameViewData,
|
||||||
|
tickExecutionDuration: last.tickExecutionDuration,
|
||||||
|
},
|
||||||
|
tileMetrics,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,11 @@ export class TickMetricsEvent implements GameEvent {
|
|||||||
public readonly workerTicksPerSecond?: number,
|
public readonly workerTicksPerSecond?: number,
|
||||||
// Approximate render tick() calls per second
|
// Approximate render tick() calls per second
|
||||||
public readonly renderTicksPerSecond?: number,
|
public readonly renderTicksPerSecond?: number,
|
||||||
|
// Tile update metrics
|
||||||
|
public readonly tileUpdatesCount?: number,
|
||||||
|
public readonly ringBufferUtilization?: number,
|
||||||
|
public readonly ringBufferOverflows?: number,
|
||||||
|
public readonly ringDrainTime?: number,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -319,6 +319,14 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
|||||||
this.layerStats.clear();
|
this.layerStats.clear();
|
||||||
this.layerBreakdown = [];
|
this.layerBreakdown = [];
|
||||||
|
|
||||||
|
// reset tile metrics
|
||||||
|
this.tileUpdatesPerRender = 0;
|
||||||
|
this.tileUpdatesPeak = 0;
|
||||||
|
this.ringBufferUtilization = 0;
|
||||||
|
this.ringBufferOverflows = 0;
|
||||||
|
this.ringDrainTime = 0;
|
||||||
|
this.totalTilesUpdated = 0;
|
||||||
|
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -437,6 +445,24 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
|||||||
@state()
|
@state()
|
||||||
private renderTicksPerSecond: number = 0;
|
private renderTicksPerSecond: number = 0;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private tileUpdatesPerRender: number = 0;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private tileUpdatesPeak: number = 0;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private ringBufferUtilization: number = 0;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private ringBufferOverflows: number = 0;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private ringDrainTime: number = 0;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private totalTilesUpdated: number = 0;
|
||||||
|
|
||||||
updateTickMetrics(
|
updateTickMetrics(
|
||||||
tickExecutionDuration?: number,
|
tickExecutionDuration?: number,
|
||||||
tickDelay?: number,
|
tickDelay?: number,
|
||||||
@@ -444,6 +470,10 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
|||||||
ticksPerRender?: number,
|
ticksPerRender?: number,
|
||||||
workerTicksPerSecond?: number,
|
workerTicksPerSecond?: number,
|
||||||
renderTicksPerSecond?: number,
|
renderTicksPerSecond?: number,
|
||||||
|
tileUpdatesCount?: number,
|
||||||
|
ringBufferUtilization?: number,
|
||||||
|
ringBufferOverflows?: number,
|
||||||
|
ringDrainTime?: number,
|
||||||
) {
|
) {
|
||||||
if (!this.isVisible || !this.userSettings.performanceOverlay()) return;
|
if (!this.isVisible || !this.userSettings.performanceOverlay()) return;
|
||||||
|
|
||||||
@@ -497,6 +527,26 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
|||||||
this.renderTicksPerSecond = renderTicksPerSecond;
|
this.renderTicksPerSecond = renderTicksPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tileUpdatesCount !== undefined) {
|
||||||
|
this.tileUpdatesPerRender = tileUpdatesCount;
|
||||||
|
this.tileUpdatesPeak = Math.max(this.tileUpdatesPeak, tileUpdatesCount);
|
||||||
|
this.totalTilesUpdated += tileUpdatesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ringBufferUtilization !== undefined) {
|
||||||
|
this.ringBufferUtilization =
|
||||||
|
Math.round(ringBufferUtilization * 100) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ringBufferOverflows !== undefined) {
|
||||||
|
// Accumulate overflows (overflows is a flag, so add 1 if set)
|
||||||
|
this.ringBufferOverflows += ringBufferOverflows;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ringDrainTime !== undefined) {
|
||||||
|
this.ringDrainTime = Math.round(ringDrainTime * 100) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,6 +577,14 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
|||||||
executionSamples: [...this.tickExecutionTimes],
|
executionSamples: [...this.tickExecutionTimes],
|
||||||
delaySamples: [...this.tickDelayTimes],
|
delaySamples: [...this.tickDelayTimes],
|
||||||
},
|
},
|
||||||
|
tiles: {
|
||||||
|
updatesPerRender: this.tileUpdatesPerRender,
|
||||||
|
peakUpdates: this.tileUpdatesPeak,
|
||||||
|
ringBufferUtilization: this.ringBufferUtilization,
|
||||||
|
ringBufferOverflows: this.ringBufferOverflows,
|
||||||
|
ringDrainTimeMs: this.ringDrainTime,
|
||||||
|
totalTilesUpdated: this.totalTilesUpdated,
|
||||||
|
},
|
||||||
layers: this.layerBreakdown.map((layer) => ({ ...layer })),
|
layers: this.layerBreakdown.map((layer) => ({ ...layer })),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -658,6 +716,21 @@ export class PerformanceOverlay extends LitElement implements Layer {
|
|||||||
Backlog turns:
|
Backlog turns:
|
||||||
<span>${this.backlogTurns}</span>
|
<span>${this.backlogTurns}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="performance-line">
|
||||||
|
Tile updates/render:
|
||||||
|
<span>${this.tileUpdatesPerRender}</span>
|
||||||
|
(peak: <span>${this.tileUpdatesPeak}</span>)
|
||||||
|
</div>
|
||||||
|
<div class="performance-line">
|
||||||
|
Ring buffer:
|
||||||
|
<span>${this.ringBufferUtilization}%</span>
|
||||||
|
(${this.totalTilesUpdated} total, ${this.ringBufferOverflows}
|
||||||
|
overflows)
|
||||||
|
</div>
|
||||||
|
<div class="performance-line">
|
||||||
|
Ring drain time:
|
||||||
|
<span>${this.ringDrainTime.toFixed(2)}ms</span>
|
||||||
|
</div>
|
||||||
${this.layerBreakdown.length
|
${this.layerBreakdown.length
|
||||||
? html`<div class="layers-section">
|
? html`<div class="layers-section">
|
||||||
<div class="performance-line">
|
<div class="performance-line">
|
||||||
|
|||||||
Reference in New Issue
Block a user