Skip to content

Commit b69941d

Browse files
committed
feat: physics system benchmarks + baseline storage (chrome)
1 parent 098ad06 commit b69941d

3 files changed

Lines changed: 476 additions & 0 deletions

File tree

fission/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
"test": "vitest",
1414
"test:coverage": "vitest run --coverage",
1515
"bench": "vitest bench --mode test",
16+
"bench:baseline": "vitest bench --mode test --project chromium --outputJson src/bench/baseline.json",
17+
"bench:chrome": "vitest bench --mode test --project chromium",
18+
"bench:firefox": "vitest bench --mode test --project firefox",
19+
"bench:ci": "vitest bench --mode test --project chromium --compare src/bench/baseline.json",
1620
"build": "tsc && vite build",
1721
"build:prod": "tsc && vite build --base=/fission/ --outDir dist/prod",
1822
"build:dev": "tsc && vite build --base=/fission-closed/ --outDir dist/dev",
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import * as THREE from "three"
2+
import { bench, describe } from "vitest"
3+
import JOLT from "@/util/loading/JoltSyncLoader"
4+
import PhysicsSystem, { STANDARD_SIMULATION_PERIOD } from "@/systems/physics/PhysicsSystem"
5+
import MirabufParser from "@/mirabuf/MirabufParser"
6+
import { getMiraAssembly } from "@/test/GetAssets"
7+
8+
function addFloor(system: PhysicsSystem) {
9+
const floor = system.createBox(new THREE.Vector3(50, 0.5, 50), undefined, new THREE.Vector3(0, -0.5, 0), undefined)
10+
system.addBodyToSystem(floor.GetID(), false)
11+
}
12+
13+
// --- Simulation step systems ---
14+
15+
const emptySystem = new PhysicsSystem()
16+
addFloor(emptySystem)
17+
18+
const eightBodySystem = new PhysicsSystem()
19+
addFloor(eightBodySystem)
20+
for (let i = 0; i < 8; i++) {
21+
const body = eightBodySystem.createBox(
22+
new THREE.Vector3(0.25, 0.25, 0.25),
23+
1.0,
24+
new THREE.Vector3((i % 4) * 0.6, Math.floor(i / 4) + 0.5, 0),
25+
undefined
26+
)
27+
eightBodySystem.addBodyToSystem(body.GetID(), true)
28+
}
29+
30+
const fiftyBodySystem = new PhysicsSystem()
31+
addFloor(fiftyBodySystem)
32+
for (let i = 0; i < 50; i++) {
33+
const body = fiftyBodySystem.createBox(
34+
new THREE.Vector3(0.25, 0.25, 0.25),
35+
0.5,
36+
new THREE.Vector3((i % 10) * 0.6, Math.floor(i / 10) * 0.6 + 0.5, 0),
37+
undefined
38+
)
39+
fiftyBodySystem.addBodyToSystem(body.GetID(), true)
40+
}
41+
42+
// --- Raycast system ---
43+
// Pass destroy=false on each rayCast call so the Vec3s survive across iterations.
44+
45+
const raycastSystem = new PhysicsSystem()
46+
const rayTarget = raycastSystem.createBox(
47+
new THREE.Vector3(1, 1, 1),
48+
undefined,
49+
new THREE.Vector3(0, 5, 0),
50+
undefined
51+
)
52+
raycastSystem.addBodyToSystem(rayTarget.GetID(), false)
53+
const RAY_FROM = new JOLT.Vec3(0, 0, 0)
54+
const RAY_HIT_DIR = new JOLT.Vec3(0, 10, 0)
55+
const RAY_MISS_DIR = new JOLT.Vec3(100, 0, 0)
56+
57+
// --- Body creation system ---
58+
59+
const creationSystem = new PhysicsSystem()
60+
const HALF_EXTENTS = new THREE.Vector3(0.5, 0.5, 0.5)
61+
const CUBE_HULL_POINTS = new Float32Array([
62+
0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5,
63+
0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5,
64+
])
65+
66+
// --- Assembly spawn systems (async: need real mirabuf assemblies) ---
67+
68+
const [dozerAssembly, multiJointAssembly] = await Promise.all([
69+
getMiraAssembly("DOZER"),
70+
getMiraAssembly("MULTI_JOINT"),
71+
])
72+
const dozerParser = new MirabufParser(dozerAssembly!)
73+
const multiJointParser = new MirabufParser(multiJointAssembly!)
74+
75+
// Separate systems per spawn bench so their internal state stays independent.
76+
const spawnSystemDozer = new PhysicsSystem()
77+
const spawnSystemMultiJoint = new PhysicsSystem()
78+
79+
// ────────────────────────────────────────────────────────────────────────────
80+
81+
describe("PhysicsSystem — simulation step", () => {
82+
bench("update — empty world", () => {
83+
emptySystem.update(STANDARD_SIMULATION_PERIOD)
84+
})
85+
86+
bench("update — 8 dynamic bodies", () => {
87+
eightBodySystem.update(STANDARD_SIMULATION_PERIOD)
88+
})
89+
90+
bench("update — 50 dynamic bodies", () => {
91+
fiftyBodySystem.update(STANDARD_SIMULATION_PERIOD)
92+
})
93+
})
94+
95+
describe("PhysicsSystem — body creation", () => {
96+
bench("createBox + add + destroy", () => {
97+
const body = creationSystem.createBox(HALF_EXTENTS, 1.0, undefined, undefined)
98+
creationSystem.addBodyToSystem(body.GetID(), false)
99+
creationSystem.destroyBodies(body)
100+
})
101+
102+
bench("createConvexHull — 8-point cube", () => {
103+
const result = creationSystem.createConvexHull(CUBE_HULL_POINTS)
104+
if (result.IsValid()) result.Get().Release()
105+
})
106+
})
107+
108+
describe("PhysicsSystem — raycast", () => {
109+
bench("rayCast — hit", () => {
110+
raycastSystem.rayCast(RAY_FROM, RAY_HIT_DIR, false)
111+
})
112+
113+
bench("rayCast — miss", () => {
114+
raycastSystem.rayCast(RAY_FROM, RAY_MISS_DIR, false)
115+
})
116+
})
117+
118+
describe("PhysicsSystem — assembly spawn", () => {
119+
// createMechanismFromParser allocates a LayerReserve (one of 8 robot slots).
120+
// destroyMechanism removes bodies and constraints but does not release the slot,
121+
// so we do it manually to keep the pool from exhausting across iterations.
122+
bench("spawn + destroy Dozer (7 bodies, 6 joints)", () => {
123+
const mech = spawnSystemDozer.createMechanismFromParser(dozerParser)
124+
spawnSystemDozer.destroyMechanism(mech)
125+
mech.layerReserve?.release()
126+
})
127+
128+
bench("spawn + destroy Multi-Joint Wheels (9 bodies, 8 joints)", () => {
129+
const mech = spawnSystemMultiJoint.createMechanismFromParser(multiJointParser)
130+
spawnSystemMultiJoint.destroyMechanism(mech)
131+
mech.layerReserve?.release()
132+
})
133+
})

0 commit comments

Comments
 (0)