mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 11:00:43 +00:00
perf(core): avoid double allocation in packMotionPlans
Rewrite MotionPlans.packMotionPlans to precompute total word count and fill a single pre-sized Uint32Array with an index pointer (no intermediate number[]).
This commit is contained in:
@@ -41,68 +41,83 @@ export type MotionPlanRecord = GridPathPlan | TrainRailPathPlan;
|
||||
export function packMotionPlans(
|
||||
records: readonly MotionPlanRecord[],
|
||||
): Uint32Array {
|
||||
const out: number[] = [MOTION_PLANS_SCHEMA_VERSION, records.length];
|
||||
|
||||
let totalWords = 2;
|
||||
for (const record of records) {
|
||||
switch (record.kind) {
|
||||
case "grid": {
|
||||
const path =
|
||||
record.path instanceof Uint32Array
|
||||
? record.path
|
||||
: Uint32Array.from(record.path);
|
||||
const pathLen = (record.path.length >>> 0) as number;
|
||||
totalWords += 2 + 5 + pathLen;
|
||||
break;
|
||||
}
|
||||
case "train": {
|
||||
const carCount = (record.carUnitIds.length >>> 0) as number;
|
||||
const pathLen = (record.path.length >>> 0) as number;
|
||||
totalWords += 2 + 7 + carCount + pathLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const out = new Uint32Array(totalWords);
|
||||
out[0] = MOTION_PLANS_SCHEMA_VERSION >>> 0;
|
||||
out[1] = records.length >>> 0;
|
||||
|
||||
let offset = 2;
|
||||
for (const record of records) {
|
||||
switch (record.kind) {
|
||||
case "grid": {
|
||||
const path = record.path as ArrayLike<number>;
|
||||
const pathLen = path.length >>> 0;
|
||||
const wordCount = 2 + 5 + pathLen;
|
||||
out.push(
|
||||
PackedMotionPlanKind.GridPathSet,
|
||||
wordCount,
|
||||
record.unitId >>> 0,
|
||||
record.planId >>> 0,
|
||||
record.startTick >>> 0,
|
||||
record.ticksPerStep >>> 0,
|
||||
pathLen,
|
||||
);
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
out.push(path[i] >>> 0);
|
||||
|
||||
out[offset++] = PackedMotionPlanKind.GridPathSet;
|
||||
out[offset++] = wordCount >>> 0;
|
||||
out[offset++] = record.unitId >>> 0;
|
||||
out[offset++] = record.planId >>> 0;
|
||||
out[offset++] = record.startTick >>> 0;
|
||||
out[offset++] = record.ticksPerStep >>> 0;
|
||||
out[offset++] = pathLen >>> 0;
|
||||
|
||||
for (let i = 0; i < pathLen; i++) {
|
||||
out[offset++] = path[i] >>> 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "train": {
|
||||
const carUnitIds =
|
||||
record.carUnitIds instanceof Uint32Array
|
||||
? record.carUnitIds
|
||||
: Uint32Array.from(record.carUnitIds);
|
||||
const carUnitIds = record.carUnitIds as ArrayLike<number>;
|
||||
const carCount = carUnitIds.length >>> 0;
|
||||
|
||||
const path =
|
||||
record.path instanceof Uint32Array
|
||||
? record.path
|
||||
: Uint32Array.from(record.path);
|
||||
const path = record.path as ArrayLike<number>;
|
||||
const pathLen = path.length >>> 0;
|
||||
|
||||
const wordCount = 2 + 7 + carCount + pathLen;
|
||||
out.push(
|
||||
PackedMotionPlanKind.TrainRailPathSet,
|
||||
wordCount,
|
||||
record.engineUnitId >>> 0,
|
||||
record.planId >>> 0,
|
||||
record.startTick >>> 0,
|
||||
record.speed >>> 0,
|
||||
record.spacing >>> 0,
|
||||
carCount,
|
||||
pathLen,
|
||||
);
|
||||
for (let i = 0; i < carUnitIds.length; i++) {
|
||||
out.push(carUnitIds[i] >>> 0);
|
||||
out[offset++] = PackedMotionPlanKind.TrainRailPathSet;
|
||||
out[offset++] = wordCount >>> 0;
|
||||
out[offset++] = record.engineUnitId >>> 0;
|
||||
out[offset++] = record.planId >>> 0;
|
||||
out[offset++] = record.startTick >>> 0;
|
||||
out[offset++] = record.speed >>> 0;
|
||||
out[offset++] = record.spacing >>> 0;
|
||||
out[offset++] = carCount >>> 0;
|
||||
out[offset++] = pathLen >>> 0;
|
||||
|
||||
for (let i = 0; i < carCount; i++) {
|
||||
out[offset++] = carUnitIds[i] >>> 0;
|
||||
}
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
out.push(path[i] >>> 0);
|
||||
for (let i = 0; i < pathLen; i++) {
|
||||
out[offset++] = path[i] >>> 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Uint32Array(out);
|
||||
if (offset !== out.length) {
|
||||
throw new Error(
|
||||
`packMotionPlans size mismatch: wrote ${offset}, expected ${out.length}`,
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function unpackMotionPlans(packed: Uint32Array): {
|
||||
|
||||
Reference in New Issue
Block a user