GUIDE 07 · DIAGNOSTICS

Measure first.
Reproduce exactly.

Glint separates visible frame throughput, fixed-step simulation cost, deterministic state verification, and seeded stress workloads so performance and correctness are inspectable.

Inspect renderer throughput

Set showStats: true on a viewport to see trailing FPS, latest frame time, draw calls, and submitted triangles.

FPS

Completed renders over the trailing second.

Frame time

Latest render wall time through GPU completion.

Draw calls

Submitted calls after culling and batching.

Triangles

Submitted triangle count for the latest frame.

Measure each fixed step

physics_profile.dartDART
physics.addStepCompletedCallback((stats) {
  debugPrint(
    'step ${stats.simulationStep}: '
    'callbacks=${stats.callbackTime.inMicroseconds}us '
    'backend=${stats.backendTime.inMicroseconds}us '
    'bodies=${stats.bodyCount} '
    'contacts=${stats.activeContactCount}',
  );
});

The callback separates gameplay fixed-callback time from native backend time and records body, active contact, and active trigger counts for that tick.

Capture rollback state

rollback.dartDART
final checkpoint = physics.captureSnapshot();

// Predict, retry, or inspect a branch.
physics.stepFixed();

physics.restoreSnapshot(checkpoint);

Snapshots retain world identity and restore the fixed-step clock, accumulator, interpolation, gravity, body transforms and velocities, sleep state, and every registered gameplay participant such as vehicles and characters.

SCOPE

Snapshots are in-memory rollback points for one live world. Portable recordings recreate the level and replay inputs instead of serializing native body handles.

Record one input per tick

replay.dartDART
final recorder = GlintPhysicsReplayRecorder<CarInput>(
  world: physics,
  applyInput: (input, fixedDt) => car.apply(input),
);

for (final input in recordedInputs) {
  recorder.record(input);
}

final replay = recorder.finish();
final result = replay.play(
  physics,
  (input, fixedDt) => car.apply(input),
);
assert(result.deterministic);

Each frame stores a quantized digest. A mismatch reports the first divergent tick instead of only showing that the final pose differs. Applications provide codecs when serializing input tapes to JSON.

Run a seeded mixed workload

stress_test.dartDART
final result = await GlintPhysicsStressRunner(
  world: physics,
  config: const GlintPhysicsStressConfig(
    bodyCount: 512,
    vehicleCount: 2,
    steps: 1200,
    queriesPerStep: 4,
  ),
).run();

expect(result.passed, isTrue);
print(result.toJson());

The workload mixes boxes, spheres, capsules, cylinders, dense contacts, impulses, ray/overlap/shape queries, optional vehicles, sleeping, escape checks, finite checks, and a final state digest.

Use layered release checks

Static

Run analyzers for the engine, example, and every optional package.

Deterministic

Run unit tests, native backend integration, replay, and seeded stress.

Build

Build iOS, macOS, and Android targets with real shader bundles and native assets.

Physical

Profile representative release workloads on physical iOS and Android hardware.