ECSY devtools

ECSY, React

Developer tools extension for ECSY



With the ECSY developer tools extension you can see an overview on the state of your ECSY application, getting statistics in realtime on how your systems are performing. Once you know which system is causing troubles in performance you can then use the browser profiler to dig into the underlying issue.

Apart from showing the status of the application, the extension lets you control the execution (eg: play/pause, step system, step frame) for debugging or learning purposes, as well as accessing the value of the queries and components used in your application.

Early prototype

When I was working on the early prototipes of ECSY I needed a way to check the state of the systems, queries and entities in the world. This is actually a pretty common requirement when building applications that require high performance- such as real time 3D graphics, AR and VR experiences- is the need to understand which part of our application is consuming more resources. You could always use the browsers’ profilers to try to understand our bottlenecks but they can be a bit unintuitive to use, and it is hard to get an overview of what is going on in the entire application, rather than focusing on a specific piece of your code.

So I built a simple overlay panel showing some stats from each system, and a button to toggle play/pause on each system.


To build this panel I was folliwng the same approach as the A-Frame inspector, injecting the panel's code into the current website.

This approach has the problem that it could affect the performance of the application as they share the same context and thread, and it could also generate conflicts with the page's style and HTML.

Building the extension

I decided to swith from an injected overlay to an extension to fix the issues with performance and potential conflicts with the application.

I started by building a proof of concept showing the state of the world in a panel and implementing simple interactions with the world from the extension, like play/stop each system:


Then I started to polish the UI and included some extra features like showing the relationship between components, queries and systems as you move your mouse over these items (I got inspired by this Overwatch Gameplay talk by Timoyhy Ford)

Once I got all the features I wanted for the initial version it was time to redesign the UI to make it look more fancy. I got inspired by the flecs tools, and Diego F. Goberna helped me a lot when building this new design.


Another of the benefits of building an extension is that you can show an icon in the toolbar and use it as a detector to tell the user that the current page is using ECSY

How do I use it?

  1. Install the extension from the extension store for your browser (Firefox, Chrome)

  2. Launch any ECSY application (For example the circle-boxes example). You will notice that the “ECSY” icon on the toolbar changes its color indicating that the ECSY library is detected:

  1. Open the ECSY tab in the browser’s developer tool (Firefox, Chrome) and you will see the state of the application.

Panel overview

When the ECSY extension panel is loaded, you will see all the sections available on the UI. (A big shout out to the flecs team as their work on their admin panel was a big inspiration for us when designing the UI)

  • (1) Main toolbar: You can control options that affect all the main panels. The buttons in order are:
    • Entities (E), Components (C), Queries (Q) and Systems (S): the buttons will toggle the visibility for each of the main panels.
    • Show relationship between components: When enabled it will highlight the relationships between Components, Queries and Systems. Eg: If you hover the Rotating component, it will highlight the Rotating query as it is using that component, as well as the RotatingSystem.
    • Show debug: Show the JSON with all the stats and info collected from the ECSY application used by the extension.
    • Show remote console (If debugging a remote device): It lets you enter commands to be executed on the remote device.
    • Show Graphs: Toggle the graphs on all the sections.
    • Show Stats: Toggle detailed stats on all the sections. This includes the following computed values for each entry:
      • Minimum
      • Maximum
      • Mean
      • Standard deviation
  • (2) Version info: Shows the version info as well as the connection details if connected to a remote device.
  • (3) Entities: The number of entities created.
  • (4) Components: Shows the number of component classes and their instances in the application.
    • This section also includes a toolbar similar to the main one:
      • Show graphs and stats: For all the components
      • Link minimum and maximum values: It will synchronize all the graphs with the maximum and minimum globals values.
      • Show pool size: It will include on each component’s graph another time series with the size of the pool for that component in red color.
      • Show detailed stats: minimum, maximum, average and standard deviation.
    • Then each component you can see:
      • Tag components: They will include a special icon to easily spot them on the list.
      • Pool detection:
        • If the component is not using a pool, it will show a warning icon indicating that it is recommended to define them as poolable for performance reasons.
        • Every time the application is creating a new component, you will see a flash message indicating if it has no pool, or the pool has no empty elements on it.
      • Dump to console: Each component has an arrow icon that will dump the list of instances of that component to the console. That list will also be assigned to a variable called $component so you can use it on the console.
  • (5) Queries: Similar to the components section, here you also have a toolbar to toggle the graph and stats visibility or toggle the graphs’ minimum and maximum values synchronization. For each query you can see the components that take part in its definition and the number of entities the query has.
  • (6) Systems: In this section you can explore all the systems being executed in your application loop and the timing for all of them. Each system shows the number of milliseconds it took to execute in the last frame, and the percentage of that time related to the whole frame time. For each query on the system you will also get extra stats if they are “reactive” (link ecsy), indicating the size of the queues for each event (added, removed or changed). You can control the execution for debugging or learning purposes:
    • World: Applied to all systems:
      • Play/Stop: Play or stop all the systems
      • Step one frame: Execute all the systems one time
      • Step next system: Execute the next system in order. Just one system at a time.
    • System
      • Play/Stop: Play or stop the specific system
      • Step: Execute the system one time.
      • Solo: Pauses all the other systems but this one. Clicking on it again will undo the action.

Remote connection

When debugging applications sometimes you want to test our code on an external device like a mobile phone or a standalone VR headset. The problem is that custom WebExtensions are not available when connecting to remote devices from the browser’s developer tools.

To address this issue I implemented a custom remote protocol using WebSockets and WebRTC, so you can connect to your device even if it is not connected via USB to your laptop, or using the same browser as you are using for debugging (eg: you could use Chrome to connect to a Firefox Reality browser on a VR device or Firefox to connect to an Oculus Browser sessions).

How to enable the developer tools remote connection in an ECSY application?

Remote connection can be enabled using two methods:

  • Explicitly calling enableRemoteDevtools() on your application.

    import {enableRemoteDevtools} from “ecsy”;
    enableRemoteDevtools( /* optional Code */);

    Please notice that you can pass an optional parameter as the code that the application will be listening for. Otherwise, a new one will be generated:

  • Adding ?enable-remote-devtools to the URL when running your application on the browser you want to connect to. Using any of the previous methods will add an overlay on your application showing a random code that will be used to connect to remotely.

How to connect a remote device?

Once you get the code from the previous section, you can connect to that device from our preferred browser by clicking the ECSY icon on the extensions toolbar, entering the code and clicking connect:

Or doing the same from the ECSY panel in the developer tools.

Features on remote devices

When using the developer tools on a remote device there are some differences from running it locally.

Console.log and errors hooks

It hooks every call to console.* as well as any error thrown by the application running on the remote device, it will send them back to the host developer tools browser and log them on the console.

Dump to console

When connected to a remote device you still have the dump to console functionality to inspect components and queries, but it works slightly differently: The remote device will serialize the data and send it to the host developer tools that will deserialize it again and call console.log with that. Note that currently the deserialization process is quite simple, so it is just preserving the raw data, but it loses all functions and data type definitions.

Remote console

I also included the ability to execute code on the remote device. Clicking on the remote console icon, the following panel will appear:

Everything you enter on the textbox will get executed on the remote device and it will write the result of the evaluation on the list above.

Case studies

When building Jumpy balls the devtools turned out to be very useful to find a bug: a leak where balls were not being deleted correctly and they just keep exponentially re-appearing:

The devtools were throwing some warnings that the pool for the affected queues were increasing on every call, and after fixing it you can see exactly what you would expect in a stable application: stable graphs on the number of components, queries and pools: