Search Unity

[Solved] 8MB gc for adding 12k components via PostUpdateCommands expected?

Discussion in 'Entity Component System' started by Timboc, Jan 25, 2019.

  1. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    238
    I've got some simple code that is designed to add a component to be used as a tag and another component with some data. Something like:
    Code (CSharp):
    1.  
    2. public struct UpdateTag: IComponentData { }
    3. public struct ComponentDataToAdd: IComponentData { public float Value; }
    4. [UpdateAfter(typeof(SomeGroup))]
    5.         public class AddTagsSystem : ComponentSystem
    6.         {
    7.             ComponentGroup compGroup;
    8.             protected override void OnCreateManager()
    9.             {
    10.                 compGroup = GetComponentGroup(
    11.                     ComponentType.ReadOnly(typeof(SomeOtherTag)),
    12.                     ComponentType.Subtractive(typeof(ComponentDataToAdd)),
    13.                     ComponentType.Subtractive(typeof(UpdateTag)) );
    14.             }
    15.  
    16.             protected override void OnUpdate()
    17.             {
    18.                 EntityArray entitiesToProcess = compGroup.GetEntityArray();
    19.  
    20.                 for (int i = 0; i < entitiesToProcess.Length; i++)
    21.                 {
    22.                     PostUpdateCommands.AddComponent<ComponentDataToAdd>(entitiesToProcess[i], new ComponentDataToAdd());
    23.                     PostUpdateCommands.AddComponent<UpdateTag>(entitiesToProcess[i], new UpdateTag());
    24.                 }
    25.             }
    26.         }
    When executing this for 6000 entities, on an i5 this takes ~60ms to execute and generates 7.8MB of GC (Jobs leak detection turned off). Is this expected? Is there a better way? I could jobify and create a barrier but my understanding is that's essentially what PostUpdateCommands is doing?

    I'm generally experiencing quite "long" times for adding/removing components and destroying entities too. I've seen @tertle's post (https://forum.unity.com/threads/batch-entitycommandbuffer.593569/) which I may check out but it seems to me this kind of pattern should be fairly common? If I'm not missing a better way, is there a chance this will be optimised in future?

    Many thanks!
     
  2. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    Are you testing this in the editor? The editor has a lot of safety check overheads that allocate managed tracking handles. This not only generates garbage but also slows things down more than would be in a player build.
     
    Timboc likes this.
  3. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    238
    Yes, in editor - though I did disable all job safety checks I could see in the menu. Sounds like a good idea for me to profile a build though.
     
  4. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    Yeah, even without the safety checks, there's editor tracking data being gc allocated.
     
  5. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    No, PUC it only queueing commands for execute them later, it no creates jobs for you. ECB always executes on main thread, it’s just queue which execute EM for every “command” one by one, without batch, it’s slow, and ECB generates GC always (edit: but not so huge). @tertle ’s solution better at this moment.
     
    Last edited: Jan 27, 2019
  6. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    I can't reproduce with those instruction, Can you make a Small project folder that has this script and produces the big amount of GC allocs.
     
  7. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    238
    Thanks @eizenhorn - good to know. Embarrassingly, I posted too soon - it was all very reproducible... until I restarted the editor :oops: - gc has all but disappeared. Speed however, running an otherwise empty project as a build with profiler attached, 10k entities results in ~25ms (~65ms in editor). This still seems a bit heavy to me(?) but maybe closer to expectations?
    upload_2019-1-26_17-52-50.png

    Rewriting to use IJobProcessComponentDataWithEntity I see the same take 82ms in editor, 30ms in build:
    upload_2019-1-26_18-7-21.png

    Sharing code used below in case I'm doing something obviously stupid. All entities are simply:
    Code (CSharp):
    1. EntityArchetype ea = entityManager.CreateArchetype(typeof(Position), typeof(Rotation), typeof(Scale));
    Jobified code:
    Code (CSharp):
    1.     public class BarrierUpdateTags : BarrierSystem { }
    2.  
    3.     public struct UpdateTag : IComponentData { }
    4.     public struct ComponentDataToAdd : IComponentData { public float Value; }
    5.     [UpdateAfter(typeof(Initialization))]
    6.     public class AddTagsSystem : JobComponentSystem
    7.     {
    8.         [Inject] BarrierUpdateTags barrier;
    9.  
    10.         [RequireSubtractiveComponent(typeof(ComponentDataToAdd))]
    11.         struct AddTagsJob : IJobProcessComponentDataWithEntity<SomeOtherTag>
    12.         {
    13.             public EntityCommandBuffer.Concurrent commandBuffer;
    14.  
    15.             public void Execute([ReadOnly] Entity entity, [ReadOnly] int index, [ReadOnly] ref SomeOtherTag tag)
    16.             {
    17.                 commandBuffer.AddComponent<ComponentDataToAdd>(index, entity, new ComponentDataToAdd());
    18.                 commandBuffer.AddComponent<UpdateTag>(index, entity, new UpdateTag());
    19.             }
    20.         }
    21.  
    22.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    23.         {
    24.             AddTagsJob job = new AddTagsJob() { commandBuffer = barrier.CreateCommandBuffer().ToConcurrent() };
    25.             return job.Schedule(this, inputDeps);
    26.         }
    27.     }
    Thanks again for all your input.
    Code attached - monobehaviour that sits on a gameobject in a scene.
     

    Attached Files:

    • Test.cs
      File size:
      3.4 KB
      Views:
      730