Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

JobTempAlloc has allocations that are more than 4 frames old

Discussion in 'Entity Component System' started by DaniParra, Apr 20, 2019.

  1. DaniParra

    DaniParra

    Joined:
    Apr 27, 2014
    Posts:
    29
    Hello,

    I have a job that copies the positions of the tanks and another job that consumes them to check the distance, for this I use a NativeArray but it shows me the following warning and I don't understand the reason.

    Code (CSharp):
    1. Internal: JobTempAlloc has allocations that are more than 4 frames old - this is not allowed and likely a leak
    Code (CSharp):
    1. using Components.Tags;
    2. using Unity.Burst;
    3. using Unity.Collections;
    4. using Unity.Entities;
    5. using Unity.Jobs;
    6. using Unity.Mathematics;
    7. using Unity.Transforms;
    8.  
    9. namespace Systems
    10. {
    11.     [UpdateInGroup(typeof(SimulationSystemGroup))]
    12.     public class BulletVsTankCollisionSystem : JobComponentSystem
    13.     {
    14.         private EntityQuery _tankGroup;
    15.         private EntityQuery _bulletGroup;
    16.        
    17.         private BeginInitializationEntityCommandBufferSystem _commandBufferSystem;
    18.        
    19.         protected override void OnCreate()
    20.         {
    21.             _tankGroup = GetEntityQuery(new EntityQueryDesc
    22.             {
    23.                 All = new[] {ComponentType.ReadOnly<Tank>(), ComponentType.ReadOnly<Translation>()},
    24.             });
    25.            
    26.             _bulletGroup = GetEntityQuery(new EntityQueryDesc
    27.             {
    28.                 All = new[] {ComponentType.ReadOnly<Bullet>(), ComponentType.ReadOnly<Translation>()},
    29.             });
    30.            
    31.             _commandBufferSystem = World.GetOrCreateSystem<BeginInitializationEntityCommandBufferSystem>();
    32.         }
    33.  
    34.         [BurstCompile]
    35.         private struct CopyPositions : IJobForEachWithEntity<Translation>
    36.         {
    37.             public NativeArray<float3> Positions;
    38.             public NativeArray<Entity> Entities;
    39.  
    40.             public void Execute(Entity entity, int index, [ReadOnly] ref Translation localToWorld)
    41.             {
    42.                 Positions[index] = localToWorld.Value;
    43.                 Entities[index] = entity;
    44.             }
    45.         }
    46.  
    47.         [BurstCompile]
    48.         [RequireComponentTag(typeof(Bullet))]
    49.         private struct CheckDistanceJob : IJobForEachWithEntity<Translation>
    50.         {
    51.             [DeallocateOnJobCompletion] [ReadOnly] public NativeArray<float3> CopyTankPositions;
    52.             [DeallocateOnJobCompletion] [ReadOnly] public NativeArray<Entity> CopyTankEntities;
    53.             [ReadOnly] public EntityCommandBuffer CommandBuffer;
    54.  
    55.             public void Execute(
    56.                 Entity entity,
    57.                 int index,
    58.                 [ReadOnly] ref Translation translation
    59.             )
    60.             {
    61.                 // TODO: Check distance, add damage...
    62.                 CommandBuffer.DestroyEntity(entity);
    63.             }
    64.         }
    65.  
    66.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    67.         {
    68.             var tankCount = _tankGroup.CalculateLength();
    69.             var copyTankPositions = new NativeArray<float3>(tankCount, Allocator.TempJob,
    70.                 NativeArrayOptions.UninitializedMemory);
    71.             var copyTankEntities = new NativeArray<Entity>(tankCount, Allocator.TempJob,
    72.                 NativeArrayOptions.UninitializedMemory);
    73.  
    74.             var copyTankPositionsJob = new CopyPositions
    75.             {
    76.                 Positions = copyTankPositions,
    77.                 Entities = copyTankEntities
    78.             };
    79.             var copyTankPositionsJobHandle = copyTankPositionsJob.Schedule(_tankGroup, inputDeps);
    80.  
    81.             var checkDistanceJob = new CheckDistanceJob
    82.             {
    83.                 CopyTankPositions = copyTankPositions,
    84.                 CopyTankEntities = copyTankEntities,
    85.                 CommandBuffer = _commandBufferSystem.CreateCommandBuffer()
    86.             };
    87.            
    88.             var checkDistanceJobHandle = checkDistanceJob.Schedule(_bulletGroup, copyTankPositionsJobHandle);
    89.  
    90.             _commandBufferSystem.AddJobHandleForProducer(checkDistanceJobHandle);
    91.          
    92.             return checkDistanceJobHandle;
    93.         }
    94.     }
    95. }
    How can I solve that? Is there a better way to do it?

    Thanks in advance.
     
  2. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    Is it maybe that your deallocations are in the CheckDistanceJob but if there's no bullets, that job is not going to run?
    I don't know what ecs does behind the scenes if the _bulletGroup is empty and whether it'll still DeallocateOnJobCompletion even if the job doesn't run.

    Maybe first check if _bulletGroup.CalculateLength() == 0 and if so just exit OnUpdate. Presumably there's no point running the tankPositions job and allocating arrays if there's no bullets?
    Otherwise you can try tack on a third job that runs regardless to deallocate the arrays, or create the arrays as instance members of BulletVsTankCollisionSystem and dispose them at the start of OnUpdate each frame.
     
    Last edited: Apr 20, 2019
  3. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    You could also try using RequireForUpdate protected method on your 2 EQ on OnCreate so that it must either run until the deallocation or not update at all.
     
  4. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    Ah I knew I forgot one. :)
    Yes RequireForUpdate in OnCreate is best option.
    Code (CSharp):
    1. protected override void OnCreate() {
    2.     ...
    3.     RequireForUpdate(_tankGroup);
    4.     RequireForUpdate(_bulletGroup);
    5. }
     
    Mikael-H likes this.
  5. DaniParra

    DaniParra

    Joined:
    Apr 27, 2014
    Posts:
    29
    Both one and the other work, I will use RequireForUpdate :D

    Thank you very much.
     
    Krajca likes this.
  6. rsodre

    rsodre

    Joined:
    May 9, 2012
    Posts:
    229
    I got this all the time, and before banging your head looking for bugs, restart Unity.
    Usually they are leaking, not me.
     
  7. w34edrtfg

    w34edrtfg

    Joined:
    Nov 23, 2014
    Posts:
    72
    I'm really glad to have read and tried this. Seems that leaving Unity open and going suspension mode it's "not supported" by Unity itself.
     
  8. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,175
    Is this correct?