mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-24 02:02:50 +00:00
perf(core): speed up packedTileUpdates (Uint32 pairs, no tile wrappers) (#3255)
## Description Reduces CPU + GC pressure from tile update serialization. **What changed** - Switched `packedTileUpdates` from `BigUint64Array` (BigInt packing) to `Uint32Array` `[tileRef, state]` pairs, updating `GameView` ingestion. - Updated tile state to use `GameMap.tileState(tile)` and `GameMap.updateTile(tile, state)`. - Removed per-tile `GameUpdateType.Tile` wrapper allocations by recording raw `(tile, state)` pairs in `GameImpl` and draining them via `drainPackedTileUpdates()` in `GameRunner`. **Why it’s faster** - Avoids BigInt and pack/unpack. - Avoids per-tile object allocations. **Compatibility** - Wire format change: `packedTileUpdates` is now `Uint32Array` pairs instead of `BigUint64Array`. ## Please complete the following: - [ ] I have added screenshots for all UI updates - [ ] I process any text displayed to the user through translateText() and I've added it to the en.json file - [ ] I have added relevant tests to the test directory - [ ] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: DISCORD_USERNAME
This commit is contained in:
+20
-18
@@ -1,7 +1,6 @@
|
||||
import { Cell, TerrainType } from "./Game";
|
||||
|
||||
export type TileRef = number;
|
||||
export type TileUpdate = bigint;
|
||||
|
||||
export interface GameMap {
|
||||
ref(x: number, y: number): TileRef;
|
||||
@@ -49,8 +48,20 @@ export interface GameMap {
|
||||
filter: (gm: GameMap, tile: TileRef) => boolean,
|
||||
): Set<TileRef>;
|
||||
|
||||
toTileUpdate(tile: TileRef): bigint;
|
||||
updateTile(tu: TileUpdate): TileRef;
|
||||
/**
|
||||
* Returns the packed per-tile state as an unsigned 16-bit value (`0..65535`).
|
||||
*
|
||||
* Backed by a `Uint16Array` in `GameMapImpl`, so callers must treat this as `uint16`.
|
||||
*/
|
||||
tileState(tile: TileRef): number;
|
||||
|
||||
/**
|
||||
* Applies a packed per-tile state value.
|
||||
*
|
||||
* `state` must be an unsigned 16-bit value (`0..65535`). Implementations may
|
||||
* store this in a `Uint16Array` and will truncate higher bits if provided.
|
||||
*/
|
||||
updateTile(tile: TileRef, state: number): void;
|
||||
|
||||
numTilesWithFallout(): number;
|
||||
}
|
||||
@@ -342,29 +353,20 @@ export class GameMapImpl implements GameMap {
|
||||
return seen;
|
||||
}
|
||||
|
||||
toTileUpdate(tile: TileRef): bigint {
|
||||
// Pack the tile reference and state into a bigint
|
||||
// Format: [32 bits for tile reference][16 bits for state]
|
||||
return (BigInt(tile) << 16n) | BigInt(this.state[tile]);
|
||||
tileState(tile: TileRef): number {
|
||||
return this.state[tile];
|
||||
}
|
||||
|
||||
updateTile(tu: TileUpdate): TileRef {
|
||||
// Extract tile reference and state from the TileUpdate
|
||||
// Last 16 bits are state, rest is tile reference
|
||||
const tileRef = Number(tu >> 16n);
|
||||
const state = Number(tu & 0xffffn);
|
||||
|
||||
const existingFallout = this.hasFallout(tileRef);
|
||||
this.state[tileRef] = state;
|
||||
const newFallout = this.hasFallout(tileRef);
|
||||
updateTile(tile: TileRef, state: number): void {
|
||||
const existingFallout = this.hasFallout(tile);
|
||||
this.state[tile] = state;
|
||||
const newFallout = this.hasFallout(tile);
|
||||
if (existingFallout && !newFallout) {
|
||||
this._numTilesWithFallout--;
|
||||
}
|
||||
if (!existingFallout && newFallout) {
|
||||
this._numTilesWithFallout++;
|
||||
}
|
||||
|
||||
return tileRef;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user