Monitor Ammo.js Heap Memory Consumption

This article explains how to monitor the memory consumption of the ammo.js physics engine heap inside a web browser. Because ammo.js is a WebAssembly (or asm.js) port of the C++ Bullet Physics engine, it manages its own memory heap independently of the standard JavaScript garbage collector, requiring specific techniques to track and optimize its footprint.

Accessing the Heap Size via JavaScript

The easiest way to programmatically monitor the memory allocated to ammo.js is by inspecting the underlying WebAssembly memory buffer. Ammo.js exposes various typed arrays (like HEAP8, HEAPF32, etc.) that share the same system memory buffer.

You can determine the total size of the allocated heap in bytes using the following JavaScript code:

function getAmmoHeapSize() {
    if (typeof Ammo !== 'undefined' && Ammo.HEAP8) {
        // Retrieve the byte length of the shared WebAssembly buffer
        const heapBytes = Ammo.HEAP8.buffer.byteLength;
        const heapMegabytes = heapBytes / (1024 * 1024);
        
        return {
            bytes: heapBytes,
            megabytes: heapMegabytes.toFixed(2)
        };
    }
    return null;
}

// Example usage:
const memory = getAmmoHeapSize();
if (memory) {
    console.log(`Ammo.js Heap Size: ${memory.megabytes} MB`);
} else {
    console.warn("Ammo.js is not loaded or initialized.");
}

This represents the total memory pool allocated to the WebAssembly instance. If ammo.js requires more memory during physics simulation, the Emscripten runtime will automatically grow this buffer (if compiled with allow-memory-growth), causing this value to increase.

Using Browser Developer Tools

For a visual representation and deep dive into ammo.js memory allocation, you can utilize the profiling tools built into modern web browsers:

  1. Chrome DevTools Performance Monitor: Open DevTools (F12), click the three dots menu -> More tools -> Performance monitor. This provides a real-time graph of “Wasm Memory”, which directly corresponds to the heap used by ammo.js.
  2. Memory Heap Snapshot: In the DevTools Memory tab, select Heap snapshot and take a profile. Search for WebAssembly.Memory or check the size of the ArrayBuffer associated with the ammo.js module to see exactly how much system memory is retained by the engine.

Preventing Heap Growth and Memory Leaks

Because JavaScript’s garbage collector cannot automatically clean up C++ objects instantiated inside ammo.js, you must manually release them to prevent the heap from growing indefinitely.

Every time you create an ammo.js object using new Ammo.bt..., you must destroy it when it is no longer needed:

// Create a physics vector
const vector = new Ammo.btVector3(0, 0, 0);

// Use the vector in your physics simulation...

// Manually destroy the object to free its memory on the heap
Ammo.destroy(vector);

Regularly monitoring Ammo.HEAP8.buffer.byteLength during gameplay or simulation runs will help you verify if your manual memory management is successful. If the heap size continuously climbs over time, it indicates a memory leak caused by missing Ammo.destroy() calls.