Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Discussion The efficiency of v1.0.11 is even lower than v0.51 !

Discussion in 'Physics for ECS' started by Bob_work, Jun 24, 2023.

  1. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    I found that v1.0.11 can only "run a set of systems" (my own definition), that is, there can only be one entity generator in a sub-scene, and the entities generated by this generator will only run in a set of physics In the simulation system (presentaiton group, simulation group, physics group in this version), I want to create several spawners in parallel, but a runtime error will occur! Even if I created XXXauthoring_2 and XXXsystem_2, they can run together without errors. However, this does nothing to improve efficiency! There is no difference between doing this and directly setting the number of entities of the original generator to 2 times!




    But in v0.51, I set 2,500 entities for each spawner, and there are 20 spawners at the same time, a total of 50,000 physical entities, the result of running down is about 16 frames. But the same 50k entities run in v1.0.11, only 2 frames!
    PS: Even if 2 units are running at the same time, my CPU still only takes up less than 70%.

    Unity official, please optimize the parallel computing of DOTS v1.0.11, don't let those groups to limit the creativity of developers.

    Of course, in the case of a single generator, v1.0.11 is much better than v0.51 when running a small number of entities, such as 10,000 entities. The former can run at 180 frames, while the latter only has about 55 frames.
     

    Attached Files:

    Last edited: Jun 25, 2023
  2. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    10,977
    Just paste the photos in your post
     
  3. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    Since I can't post images right now, I'll explain it shortly. When v1.0.11 runs 50,000 physical entities (whether it is 1 spawner or 2 systems and 2 spawners), there will be an IDLE state of more than 340ms (under several "Jobhandle.Complete"), and one frame only takes 450ms (Only a poor 2.2 fps).!!!
    This is obviously because there are too many physical entities, which makes it impossible for a single system (this system not DOTS system, just I call it system, you can realize as a group of thread of running simulation and physics) to handle it. In v0.51, 20 sets of spawners (I don't know, but I guess maybe there are 20 queries or 20 entitymanagers behind it? But certainly not 20 worlds ) also run 50,000 physical entities, but they can run to 16.9 frame!!!
     
  4. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    thanks buddy
     
  5. zhangdong304

    zhangdong304

    Joined:
    Mar 21, 2018
    Posts:
    23
    (Big brother, in your picture all are chinese hahahhaha. Don't know they old-out can not can translate it.)
    I have the same problem. Version 0.51 is much better than version 1.0.
     
    Unifikation likes this.
  6. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    I'm just too lazy to take new screenshots :)
     
  7. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    Officials, you should read my post carefully!
    This time your v1.0.11 is really not done well.

    upload_2023-6-25_23-35-32.png

    If I don't catch the screen, it will stable with 12 FPS. I am quite satisfied with this CPU usage (over 90%).

    When I press the WSAD key, these balls roll with friction. Oh, this is use havok.
     
    Last edited: Jun 25, 2023
    Unifikation and zhangdong304 like this.
  8. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,026
    南辕北辙

    It's not the first time. Won't be the last. Particles and visual effects noticeably worse since mid March.
     
  9. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    How can I give you a thumbs up
     
    Unifikation likes this.
  10. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    210
    @Bob_work : I am trying to understand what the core issue is that you are describing. Let me try and confirm my understanding.

    Recently, the physics simulation speed has been confirmed to be comparable between 0.51 and 1.0 here (and in my other, earlier responses in the same thread).
    So, here you are saying in your original post that it's the spawning process that is slow, not the simulation speed. Is that correct?

    If you would like us to drill further into this issue, we would need to get some more information, such as either profiler screenshots that, among others, shows the number of physics steps performed per frame and the sequence of Jobs that are executed for each physics step, or access to a project that reproduces this issue on 0.51 and 1.0.
    Please note that there could be many steps done as part of one FixedStepSimulationSystemGroup update in your scene in 1.0 btw, slowing things down significantly. This can be caused by to the workings of the FixedRateCatchupManager which is trying to achieve real-time rates via additional physics updates, and fails to achieve this given that the scene is by design not real-time.

    As I mentioned here, you can force there to be ever only one physics step per frame by swapping out the default rate manager for another one that always just performs one step.
     
  11. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    Thank you for your reply, but you really misunderstood.

    I don't know what is done behind DOTS, and there are only several words that can describe it, so the “system” I will talk about below is not a DOTS system, but a description of a single operating environment.

    First of all, it is not that the generator is slow to generate entities, but in 0.51, the overall operating efficiency of entities generated by multiple generators (such as 20 generators) at runtime is much higher than that of the same entities generated by a single generator.

    Second, I found that v1.0.11 can no longer use multiple generators to generate entities like 0.51. Instead, only one authoring and one system can be used to process all entities (20 times). But on the same PC, with the same large number of entities, the running efficiency of v1.0.11 is far from that of v0.51! My pictures have shown that the "single system" of v1.0.11 has only 2 frames when running 50,000 entities, while the same PC v0.51 can run 120,000 entities and still have 10 frames.

    My code for v0.51 comes from 1c3. DOTS GravityWell of EntityComponentSystemSamples-master. I found that GravityWell performance with only 1 generator was also poor (about 30% of v1.0.11), so I changed 1 generator to 20 generators in 2022, and the efficiency is as you can see up.

    In addition, last year I found that the real hindrance to performance is: when a system handles too many entities, there will be a lot of waiting time for thread dispatching. In the past, it was only observed that dispatch was consuming a lot of time. Now v1.0.11 shows that it is Job.Complete is waiting for the thread, and there is a lot of IDLE time. The way I deal with it is: spread too many entities into more threads. Because I found that when the number of entities in a thread is not large, DOTS is very efficient, and there is basically no waiting state. But in v1.0.11, groups such as presentation, simulation, and physics are now added, so that developers can no longer modify the code and create multiple spawners to distribute entities to parallel systems (I don't know why v0.51 can).
     
    Last edited: Jun 27, 2023
  12. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    210
    I encourage you to file a bug with reproduction steps of the issue so that we can look into this in more detail.
    Your description alone is unfortunately not sufficient for me to provide you with any guidance in this matter or to understand what exactly the root cause for the issue you are describing is.
     
  13. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    You don't need the whole project, do you?

    This is v0.51 spawner script.
    In fact, there is no difference between my code and the official sample code of unity. I just mounted this script onto 20 generator entities.

    (compared with ..\PhysicsSamples\Assets\Common\Scripts\SpawnRandomObjectsAuthoring.cs)

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;   //Add by Bob, 2022-09-16.
    5. using Unity.Mathematics;
    6. using Unity.Physics.Systems;
    7. using Unity.Transforms;
    8. using UnityEngine;
    9.  
    10. class SpawnRandomObjectsAuthoring : SpawnRandomObjectsAuthoringBase<SpawnSettings>
    11. {
    12. }
    13.  
    14. abstract class SpawnRandomObjectsAuthoringBase<T> : MonoBehaviour, IConvertGameObjectToEntity, IDeclareReferencedPrefabs
    15.     where T : struct, IComponentData, ISpawnSettings
    16. {
    17.     #pragma warning disable 649
    18.     public GameObject prefab;
    19.     public float3 range = new float3(10f);
    20.     [Tooltip("Limited to 500 on some platforms!")]
    21.     public int count;
    22.     #pragma warning restore 649
    23.  
    24.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    25.     {
    26.         var spawnSettings = new T
    27.         {
    28.             Prefab = conversionSystem.GetPrimaryEntity(prefab),
    29.             Position = transform.position,
    30.             Rotation = transform.rotation,
    31.             Range = range,
    32.             Count = count
    33.         };
    34.         Configure(ref spawnSettings, entity, dstManager, conversionSystem);
    35.         Configure(ref spawnSettings);
    36.         dstManager.AddComponentData(entity, spawnSettings);
    37.     }
    38.  
    39.     internal virtual void Configure(ref T spawnSettings) {}
    40.     internal virtual void Configure(ref T spawnSettings, Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) {}
    41.     internal virtual void Configure(List<GameObject> referencedPrefabs) { referencedPrefabs.Add(prefab); }
    42.  
    43.     public void DeclareReferencedPrefabs(List<GameObject> referencedPrefabs) => Configure(referencedPrefabs);
    44. }
    45.  
    46. interface ISpawnSettings
    47. {
    48.     Entity Prefab { get; set; }
    49.     float3 Position { get; set; }
    50.     quaternion Rotation { get; set; }
    51.     float3 Range { get; set; }
    52.     int Count { get; set; }
    53. }
    54.  
    55. struct SpawnSettings : IComponentData, ISpawnSettings
    56. {
    57.     public Entity Prefab { get; set; }
    58.     public float3 Position { get; set; }
    59.     public quaternion Rotation { get; set; }
    60.     public float3 Range { get; set; }
    61.     public int Count { get; set; }
    62. }
    63.  
    64. class SpawnRandomObjectsSystem : SpawnRandomObjectsSystemBase<SpawnSettings>
    65. {
    66. }
    67.  
    68. [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    69. [UpdateBefore(typeof(BuildPhysicsWorld))]
    70. abstract partial class SpawnRandomObjectsSystemBase<T> : SystemBase where T : struct, IComponentData, ISpawnSettings
    71. {
    72.     internal virtual int GetRandomSeed(T spawnSettings)
    73.     {
    74.         var seed = 0;
    75.         seed = (seed * 397) ^ spawnSettings.Count;
    76.         seed = (seed * 397) ^ (int)math.csum(spawnSettings.Position);
    77.         seed = (seed * 397) ^ (int)math.csum(spawnSettings.Range);
    78.         return seed;
    79.     }
    80.  
    81.     internal virtual void OnBeforeInstantiatePrefab(ref T spawnSettings) {}
    82.  
    83.     internal virtual void ConfigureInstance(Entity instance, ref T spawnSettings) {}
    84.  
    85.     protected override void OnUpdate()
    86.     {
    87. //#if BACKUP
    88.         // Entities.ForEach in generic system types are not supported
    89.         using (var entities = GetEntityQuery(new ComponentType[] { typeof(T) }).ToEntityArray(Allocator.TempJob))
    90.         {
    91.             for (int j = 0; j < entities.Length; j++)
    92.             {
    93.                 var entity = entities[j];
    94.                 var spawnSettings = EntityManager.GetComponentData<T>(entity);
    95.  
    96. #if UNITY_ANDROID || UNITY_IOS || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
    97.                 // Limit the number of bodies on platforms with potentially low-end devices
    98.                 var count = math.min(spawnSettings.Count, 500);
    99. #else
    100.                 var count = spawnSettings.Count;
    101. #endif
    102.  
    103.                 OnBeforeInstantiatePrefab(ref spawnSettings);
    104.                 var instances = new NativeArray<Entity>(count, Allocator.Temp);
    105.                 EntityManager.Instantiate(spawnSettings.Prefab, instances);
    106.  
    107.                 var positions = new NativeArray<float3>(count, Allocator.Temp);
    108.                 var rotations = new NativeArray<quaternion>(count, Allocator.Temp);
    109.  
    110.                 RandomPointsInRange(spawnSettings.Position, spawnSettings.Rotation, spawnSettings.Range, ref positions, ref rotations, GetRandomSeed(spawnSettings));
    111.  
    112.                 for (int i = 0; i < count; i++)
    113.                 {
    114.                     var instance = instances[i];
    115.                     EntityManager.SetComponentData(instance, new Translation { Value = positions[i] });
    116.                     EntityManager.SetComponentData(instance, new Rotation { Value = rotations[i] });
    117.  
    118.                     ConfigureInstance(instance, ref spawnSettings);
    119.                 }
    120.  
    121.                 EntityManager.RemoveComponent<T>(entity);
    122.             }
    123.         }
    124. //#endif
    125.     }
    126.  
    127.     protected override void OnCreate()
    128.     {
    129.         base.OnCreate();
    130.         //InitEntityEcbS = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    131.         Application.targetFrameRate = -1;
    132.     }
    133.  
    134.     protected static void RandomPointsInRange(
    135.         float3 center, quaternion orientation, float3 range,
    136.         ref NativeArray<float3> positions, ref NativeArray<quaternion> rotations, int seed = 0)
    137.     {
    138.         var count = positions.Length;
    139.         var random = new Unity.Mathematics.Random((uint)seed);
    140.         for (int i = 0; i < count; i++)
    141.         {
    142.             positions[i] = center + math.mul(orientation, random.NextFloat3(-range, range));
    143.             rotations[i] = math.mul(random.NextQuaternionRotation(), orientation);
    144.         }
    145.     }
    146. }
    ====================================================================================


    v1.0.11 code as below.
    This is very basic code, but this authoring can only be used in one generator, otherwise errors will be reported. Even if I use the naming method of authoring_2 and system_2 to generate a second batch of the same entities, the efficiency is no different from putting 2 batches of entities together to generate them.

    Authoring
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Entities;
    4. using Unity.Mathematics;
    5. using Unity.Transforms;
    6. using Unity.VisualScripting;
    7. using UnityEngine;
    8.  
    9. struct BallGenerator : IComponentData
    10. {
    11.     public Entity BallProtoType;
    12.     public float3 SpawnRange;
    13.     public int BallCount;
    14.     public float3 CneterPos;
    15.     public quaternion Orientation;
    16. }
    17.  
    18. public class BallGeneratorAuthoring : MonoBehaviour
    19. {
    20.     public GameObject ballPrefab = null;
    21.     public float3 range = new float3(10f);
    22.     public int count;
    23.     private float3 spawnerPos;
    24.     private quaternion rotation;
    25.  
    26.     class BallGeneratorBaker : Baker<BallGeneratorAuthoring>
    27.     {
    28.         public override void Bake(BallGeneratorAuthoring authoring)
    29.         {
    30.             Debug.Log("Ball Generator Baker");
    31.             authoring.spawnerPos = GetComponent<Transform>().localPosition;
    32.             authoring.rotation = GetComponent<Transform>().rotation;
    33.  
    34.             AddComponent(new BallGenerator
    35.             {
    36.                 BallProtoType = GetEntity(authoring.ballPrefab),
    37.                 SpawnRange = authoring.range,
    38.                 BallCount = authoring.count,
    39.                 CneterPos = authoring.spawnerPos,
    40.                 Orientation = authoring.rotation,
    41.             });
    42.         }
    43.     }
    44. }
    45.  
    System
    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Entities.UniversalDelegates;
    5. using Unity.Mathematics;
    6. using Unity.Transforms;
    7. using UnityEngine;
    8.  
    9. [BurstCompile]
    10. [RequireMatchingQueriesForUpdate]
    11. public partial struct BAllGenerateSystem : ISystem
    12. {
    13.     [BurstCompile]
    14.     public void OnCreate(ref SystemState state)
    15.     {
    16.         Debug.Log("BAll Generate System OnCreate");
    17.         state.RequireForUpdate<BallGenerator>();
    18.     }
    19.  
    20.     [BurstCompile]
    21.     public void OnDestroy(ref SystemState state)
    22.     {
    23.         Debug.Log("BAll Generate System OnDestroy");
    24.     }
    25.  
    26.     [BurstCompile]
    27.     public void OnUpdate(ref SystemState state)
    28.     {
    29.         Debug.Log("BAll Generate System OnUpdate");
    30.  
    31.         var generator = SystemAPI.GetSingleton<BallGenerator>();
    32.         var balls = CollectionHelper.CreateNativeArray<Entity>(generator.BallCount, Allocator.Temp);
    33.         state.EntityManager.Instantiate(generator.BallProtoType, balls);
    34.  
    35.         int count = 0;
    36.         int seed = 7;
    37.         var random = new Unity.Mathematics.Random((uint)seed);
    38.         foreach (var ball in balls)
    39.         {
    40.             float3 position;
    41.             quaternion rotation;
    42.             position = generator.CneterPos + math.mul(generator.Orientation, random.NextFloat3(-generator.SpawnRange, generator.SpawnRange));
    43.             rotation = math.mul(random.NextQuaternionRotation(), generator.Orientation);
    44.  
    45.             var transform = SystemAPI.GetAspectRW<TransformAspect>(ball);
    46.             transform.LocalPosition = position;
    47.             transform.LocalRotation = rotation;
    48.             count++;
    49.         }
    50.  
    51.         balls.Dispose();
    52.         state.Enabled = false;
    53.     }
    54. }    
     
  14. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    210
    Thanks. What's in the prefab you are spawning?
     
  15. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    Just normal sphere, with "physics Body" and "physics Shape" and "PhysicsRenderEntity"(Authoring). I also add a script with name "ApplyBallRollingAuthoring" which control ball rolling by WSAD keys. Last is an "Universal Render Pipeline/Lit" Material.
     
  16. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    210
    I am not sure how you are creating these "independent systems" (not DOTS systems as you say, but independent processing streams if you will) in 0.51, and why you are failing to recreate the same setup in 1.0.11. Therefore, to allow us to reliably reproduce the situation you are describing and see what you are seeing, I would recommend that you file a bug report and provide two projects (one for 0.51, and one for 1.0.11) with reproduction steps.
     
  17. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,026
    Is anyone at Unity making a good faith effort to pursue the maintenance of (and increases within) performance from 0.51 to and through subsequent "production ready" releases?

    Or is it true that performance has declined in the march to full point release?

    If that is true, simply stating that would at least give the OP some sense of sanity.
     
  18. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    210
    Absolutely. I can only speak for the physics side of things, but we are 100% invested into ensuring that we provide the best performance and stability and prevent any performance regressions.
    I've recently looked into a similar concern about performance and was able to show that there was no regression between 0.51 and 1.0 in the case shared by the client. See here for details of the investigation.

    The problem here is simply that it will be hard to impossible for us to reproduce exactly what OP is seeing without a project for reproduction, specifically concerning the "independent (non-DOTS) systems" that OP said they created.
     
  19. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    If possible, I would prefer to send the projects to you.
     
  20. daniel-holz

    daniel-holz

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    210
    That's unfortunately not possible since it might be someone else from the team that looks into this. The bug reporting feature allows you to attach your projects.
     
  21. Bob_work

    Bob_work

    Joined:
    May 5, 2020
    Posts:
    108
    To put it more vividly, this "independent system" is more like the world of unity. Each world has its own independent loop system, so multiple worlds are more efficient than a single world when dealing with a large number of generated entities at the same time.
    This is because a single world has little (or even no) waiting time (IDLE) when processing a small number of entities, while a single world will spend a lot of time waiting when processing a large number of entities.
    Of course, I don't know how the system is really implemented in the backaground, but based on my experience, I guess it's pretty close.