Search Unity

Huge amount Garbage Allocation with entities (and Post Processing i think)

Discussion in 'Data Oriented Technology Stack' started by Nautiliod, Aug 11, 2019.

  1. Nautiliod

    Nautiliod

    Joined:
    Oct 23, 2018
    Posts:
    5
    Hello guys,

    i hope this isnt a newbie-thing since im new... but i searched the web for 2 days straight and have not found a clue.
    Garbage Allocation is causing me some trouble with Entities in an extremely Simple Scene. Essentially I spawn in some entities and then i get about 180kb - 350 kb allocated each frame. There is not even an Update Function in the Script.... and performance is good with zero entities, horrible with 5 and only slightly worse with >50k entities. No Jobs or Systems are affecting the entities.
    So to test just created a new Project and loaded the spawner-script and viola, 50k entities run smooth with >200 fps.
    I was using HDRP for the entire time, but i just recently implemented Post Processing and i think this is where the problem is since this problem arose just recently (disabling the empties with the PP volumes or different Camera settings didn't fix the problem tho...) (occlusion Culling with no effect).
    Did some Allocation Callstacks but i dont know how to interpret the results, see Pictures.
    Thank you!


    Spawner Script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Transforms;
    5. using Unity.Entities;
    6. using Unity.Mathematics;
    7. using Unity.Rendering;
    8.  
    9.  
    10.  
    11.  
    12. public class GameHandler : MonoBehaviour
    13. {
    14.    
    15.     [SerializeField] private Mesh levelMesh;
    16.     [SerializeField] private Material levelMaterial;
    17.  
    18.  
    19.  
    20.     private static EntityManager entityManager;
    21.  
    22.  
    23.     void Start()
    24.     {
    25.         entityManager = World.Active.EntityManager;
    26.  
    27.         for (int i = 0; i < 50000; i++)
    28.         {
    29.             Quaternion rotation = new Quaternion();
    30.             rotation.eulerAngles = new Vector3(UnityEngine.Random.Range(0f, 360f), UnityEngine.Random.Range(0f, 360f), UnityEngine.Random.Range(0f, 360f));
    31.             SpawnLevelEntity(
    32.                 new float3(UnityEngine.Random.Range(-5000f, 5000f), UnityEngine.Random.Range(-20f, 20f), UnityEngine.Random.Range(-5000f, 5000f)),
    33.                 rotation,
    34.                 new float3(UnityEngine.Random.Range(0f, 15f), UnityEngine.Random.Range(0f, 15f), UnityEngine.Random.Range(0f, 15f))
    35.                  );
    36.  
    37.         }
    38.     }
    39.  
    40.  
    41.  
    42.  
    43.     private void SpawnLevelEntity(float3 position, quaternion rotation, float3 scale)
    44.     {
    45.         Entity entity = entityManager.CreateEntity(
    46.  
    47.             typeof(LocalToWorld),
    48.             typeof(Translation),
    49.             typeof(Rotation),
    50.             typeof(NonUniformScale),
    51.  
    52.             typeof(RenderMesh),
    53.             typeof(Level),
    54.             typeof(Collider)
    55.  
    56.             );
    57.  
    58.  
    59.  
    60.         SetEntityComponentData(entity, position, rotation, scale, levelMesh, levelMaterial);
    61.     }
    62.  
    63.  
    64.  
    65.     private void SetEntityComponentData(Entity entity, float3 spawnPosition, quaternion spawnRotation, float3 scale, Mesh mesh, Material material)
    66.     {
    67.         entityManager.SetSharedComponentData<RenderMesh>(entity,
    68.             new RenderMesh
    69.             {
    70.                 mesh = mesh,
    71.                 material = material,
    72.             });
    73.  
    74.         entityManager.SetComponentData<Translation>(entity,
    75.            new Translation
    76.            {
    77.                Value = spawnPosition
    78.            });
    79.         entityManager.SetComponentData<Rotation>(entity,
    80.           new Rotation
    81.           {
    82.               Value = spawnRotation
    83.           });
    84.         entityManager.SetComponentData<NonUniformScale>(entity,
    85.         new NonUniformScale
    86.         {
    87.             Value = scale
    88.         });
    89.  
    90.  
    91.     }
    92. }
    93.  
    94. public struct Player : IComponentData { }
    95. public struct Level : IComponentData { }
    96. public struct Collider : IComponentData
    97. {
    98.     public bool IsClose;
    99.     public bool HasCollider;
    100. }
    101.  
    102.  

    Pictures:
    5 Entities Hierarchy:
    5e.PNG
    50k Entities Hierarchy:
    50ke.PNG
    50k Entities TimeLine:
    50ke TL.PNG
    Callstacks1
    Callstacks TL.PNG
    Callstacks2
    Callstacks TL2.PNG
     
  2. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    Hi!
    Looking at the callstack the allocation is coming from NativeArray safety system - DisposeSentinel.
    The system is used to ensure there are no race conditions when you use NativeArray with JobSystem.
    In the Player it is controlled by
    ENABLE_UNITY_COLLECTIONS_CHECKS
    define which is not defined in Release builds. You can not disable it in the Editor afaik.
     
  3. Nautiliod

    Nautiliod

    Joined:
    Oct 23, 2018
    Posts:
    5
    Thanks for your reply. Not sure how the DisposeSentinel is active without any Jobs being scheduled, since the only Script active was the one i postet. I have other Job-Scripts wich do work with NativeArrays, but i commented them out entirely.
    The got around this problem by creating an empty Project and recreating the entire thing...Post Processing is active aswell. Now it runs as it did before with over 150fps, 50k entities and they even get scanned every frame for the closest to the player and shifted back to origin from time to time. DOTS is just awesome.
     
    alexeyzakharov likes this.
  4. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    Glad to hear you are not blocked, thanks for following up!

    I think you can use Jobs->Burst->Safety Checks menu to dynamically enable/disable collection checks.