Benchmark Matter.js CPU Time Using console.time

Benchmarking CPU execution time per physics frame in Matter.js allows you to measure engine overhead, identify complex collision bottlenecks, and ensure smooth simulation performance. This guide demonstrates how to monitor physics updates using the browser's native console.time and console.timeEnd methods by intercepting the Matter.js engine update loop.

Using Matter.js Engine Events

Matter.js provides built-in lifecycle hooks via its Events module. To measure the exact duration of a single engine step when using Matter.Runner, wrap the update cycle with beforeUpdate and afterUpdate listeners:

const { Engine, Runner, Events } = Matter;

const engine = Engine.create();
const runner = Runner.create();

// Start the timer immediately before the engine computes the frame
Events.on(engine, 'beforeUpdate', () => {
  console.time('Physics Frame');
});

// Stop the timer and log the result immediately after calculations finish
Events.on(engine, 'afterUpdate', () => {
  console.timeEnd('Physics Frame');
});

Runner.run(runner, engine);

Benchmarking in a Custom Animation Loop

If you manage your simulation cycle manually via requestAnimationFrame instead of using Matter.Runner, place the timing calls directly around Engine.update:

const { Engine } = Matter;
const engine = Engine.create();

function gameLoop(timestamp) {
  // Start execution timer
  console.time('Manual Physics Step');

  // Execute physics computation
  Engine.update(engine, 1000 / 60);

  // End execution timer
  console.timeEnd('Manual Physics Step');

  requestAnimationFrame(gameLoop);
}

requestAnimationFrame(gameLoop);

Avoiding Console Logging Overhead

Running console.timeEnd at 60 frames per second prints 60 lines per second to the developer console. The input/output cost of writing to the console consumes significant CPU resources and skews benchmarking data.

To obtain accurate measurements without degrading performance, sample the execution time periodically:

let frameCount = 0;
const sampleRate = 60; // Log once every 60 frames (roughly once per second)

Events.on(engine, 'beforeUpdate', () => {
  if (frameCount % sampleRate === 0) {
    console.time('Sampled Physics Frame');
  }
});

Events.on(engine, 'afterUpdate', () => {
  if (frameCount % sampleRate === 0) {
    console.timeEnd('Sampled Physics Frame');
  }
  frameCount++;
});

Key Considerations