Excalibur icon indicating copy to clipboard operation
Excalibur copied to clipboard

PointerEventReceiver memory leak

Open blakearoberts opened this issue 11 months ago • 2 comments

Steps to Reproduce

  1. Instantiate and start an engine in any configuration.
  2. Add and initialize any scene that removes the default PointerSystem (e.g. this.world.remove(this.world.get(PointerSystem))).
  3. Move, click, or scroll your mouse.

The culprit of the issue is a combination of these two pieces of code:

  1. PointerEventReceiver appends pointer events to internal arrays that are cleared via an external call of its clear method.
  2. PointerSystem is currently responsible for the external call to the receiver's clear method: https://github.com/excaliburjs/Excalibur/blob/main/src/engine/Input/PointerSystem.ts#L163.

Expected Result

When removing the default PointerSystem, the engine or scene do not allocate or retain memory related to pointer events.

Actual Result

For every native pointer event:

  • Two event listener handlers are invoked (one for the engine and one for the scene).
  • Two references per pointer event are retained indefinitely (one by the by the engine's PointerEventReceiver and one by the scene's PointerEventReceiver).

Environment

  • browsers and versions: Chrome 131.0.6778.265
  • operating system: MacOS
  • Excalibur versions: 0.30.3
  • The memory leak does not depend on the environment.

Current Workaround

Detach both input receivers when initializing the scene that removes the default pointer system:

  public override onInitialize(): void {
    this.world.remove(this.world.get(PointerSystem));
    this.input.pointers.detach();
    this.engine.input.pointers.detach();
  }

Potential Quick Fix

Normally, the PointerSystem calls clear() on both input receivers at the end of its update loop. Alternatively (or additionally), clear() could be called by the pointer event receiver itself as the first step to its update().

Potential Robust Fix

The quick fix is not ideal because it still incurs superfluous allocation and execution. Rather than having the engine and scene manage pointer event listeners, the pointer system itself should manage the listeners. This way the system can remove the listeners when deactivated, disabled, disposed, and/or removed.

blakearoberts avatar Feb 01 '25 20:02 blakearoberts

@blakearoberts Thanks for the bug! Definitely an issue...

I do agree that perhaps pointer management should wholly be contained within the PointerSystem. It definitely feels right.

The current state is a vestige of Excalibur's evolution over time to an ECS based engine.

eonarheim avatar Feb 02 '25 21:02 eonarheim

This issue hasn't had any recent activity lately and is being marked as stale automatically.

github-actions[bot] avatar Apr 04 '25 00:04 github-actions[bot]