Garbage for every OnUpdate when using ECS

Hey there,

I’m relatively new to ECS and wonder if it’s okay that every system I have allocates memory each frame. E.g. a very simple one for energy regeneration:

using Unity.Entities;
using UnityEngine;

public class EnergyRegenerationSystem : ComponentSystem {

    protected override void OnUpdate() {
        Entities.ForEach((ref EnergyData data) => {
            if (data.CurrentEnergy >= data.MaxEnergy) return;

            data.CurrentEnergy += data.RegenerationRate * Time.deltaTime;

            if (data.CurrentEnergy <= data.MaxEnergy) return;

            data.CurrentEnergy = data.MaxEnergy;
        });
    }

}

It seems when ForEach is executed a new NativeArray and underlying a new List ist created.

I’m using Unity 2019.2.17f1 on Windows with Entities 0.1.1.

Is this a bug, intention or am I just doing something wrong?

Profile this in a build, should be gone there. This is due to safety checks in editor.

If you use the new Entities.Foreach feature in JobComponentSystem instead of ComponentSystem, you can do this without garbage and with burst.

2 Likes

Unless I’m mistaken I think it’s from the lambda - the old ComponentSystem doesn’t do the compile time magic to avoid the GC allocations when using lambdas.

As a workaround im creating local function and put them in Delegates then pass the Delegates to the Entities.foreach which prevent the creation of GC on every frame. This is working for me.

Like Lucas said you should really just be using JobComponentSystem now, it lets you do the foreach lambda with no allocations and it will run faster than ComponentSystem even for main thread code. See the dots pong tutorial for an explanation.

Is it worth it when there aren’t many entities for the system?

Yes. In the latest version of Entities JobComponentSystem will run faster and avoid the allocation problems ComponentSystem has, so there’s no reason not to use it instead. I wouldn’t be surprised if ComponentSystem ends up being deprecated at some point. Just watch the video I provided in my previous post for a better explanation.

1 Like

It’s already. Joachim mentioned that they will remove ComponentSystem and JobComponentSystem will be one full covering solution for main thread and jobified code.

2 Likes

Nice!! i didnt know about it. im going to watch it now :slight_smile:
i like this way Unity’s is initiating it’s Community to ECS!

there is something im not understanding in this new way of writing Multithreaded Code by using the Entities.ForEach to replace the old way of doing things like ‘IJobParallelFor…’.
in the video he disabled the BurstCompile just because it’s using a static not ReadOnly variable inside the job. which is really a bad Approach, because Burst is amazingly optimizing performance even on main Thread.
in the old way it’s as simple as passing a copy of the value as readonly to the Job,but how to do this in the new ECS way of scripting ?

Basically you assign any outside data to a local variable just before you run the ForEach and then use that local variable in the ForEach as normal. If you need to it to be accessed as read only, you do

var something = Whatever
inputDeps = Entities.
    WithReadOnly(something).
    Foreach(...

The manual page for the new ForEach is actually surprisingly thorough and detailed. Highly recommended for learning the new syntax.

I’m finding lots of resources for the new syntax, but where can I find more details about how the compiler avoids creating garbage in this situation?

Not much for now except for the source code. Just assume that unity replaces this with code generation which generates code that avoids garbage.

DOTS → DOTS Compiler → Open Inspector. Will show you which code will be generated for systems, you can inspect and see how it works.

2 Likes

Does Tiny use the same compiler, or for now, will garbage still be generated in Tiny if you use delegates?