Question about DOTS performance

Hello, first of all, i want to clear out that i am not qualified to make comments on the subject. I am learning developer who is very inexperienced in game development and coding.

However i like to follow stuff happening related to Unity frequently mostly because i am enjoying to see things improve even if they do not affect my life immediately. An hour ago i was searching Youtube for latest Unity related videos, then i coincided into this video that attract my attention.

. This guy on the video compares DOTS performance vs hand-written code of his own on one of the DOTS sample projects.

I do not know what is to be expected or how much the results he demonstrate represents the reality. But we are talking about really huge performance difference. I would love to hear more experienced developers opinions about this including Unity dev teams.

Its not that i would try to do thing on my own if this performance comparison is realistic, first i just can’t and secondly i don’t want to put any extra effort anyway. But i want to know the limits and reality of performance deficiency using Unity over anything more optimal.

Thank you for reading, Kaan.

1 Like

Suggest reading the DOTS forum posts because your question is answered there fully. Feel free to disclose your native language so people who have good experience in both languages can help you better.

Hi thank you for the reply. I looked a bit couldnt find the answer though. If we are talking about the language i have most experience with then it is C. Between C++ and C# i guess i like C# better.

  1. The project in question is not so much an official Unity sample as much as it is a sample written by one guy in the Unity Evangelists team who is learning DOTS himself. Many of the algorithms are suboptimal but were easy to implement and he even made a comment about this himself.

  2. The video creator has provided nothing regarding what algorithms or multithreading solutions he used. I suspect he is using superior algorithms and a serial-wide threading model which is what Unity’s ECS simple dependency mode does.

  3. I suspect the hybrid renderer is the bottleneck in the Unity project. There are known performance issues when rendering large amounts of moving objects. It’s about 10x slower than what it should be which correlates well with the video. The good news is that this is still in preview and will be fixed, but also that Unity DOTS is modular enough that if you don’t like something, you can write your own replacement with as much effort as it would take to implement such a feature in a scratch C++ project.

Thank you, i was hoping to hear either that sample code wasnt optimized or at least hoping it was about an issue going to be fixed.

Definetely wouldnt want to hear that it was limit of the architecture because eventhough i am not invested in dots yet.
I plan to migrate coding in it when learning materials become more mainstream and stability is considered satisfactory by general consensus .Even if it would not reached its potential yet.

The code/project is available on github:
https://github.com/ntcaston/AngryGL

Nice! That link wasn’t there when I checked earlier.

It’s pretty much what I suspected. He’s using a better broadphase collision detection system, but a more expensive and more accurate narrow phase. Threading is similar too. He runs collision single-threaded but most transform-related things in parallel just like the Unity project. So collision and rendering appear to be the main differentiating factors.

1 Like

In 2019.3 with updated packages this is one of the results:

As @DreamingImLatios said, collision, rendering and additonally, the ECS end simulation (TRSToLocalToWorld) are the bottlenecks.
I’m pretty sure those issues can be solved. Joachim already mentioned rendering improvements but I think those were for non-moving entities, so fingers crossed.

The system is currently only optimized for non-moving entities. That’s what Megacity needed.

Anyone got burst to run in this with newest packages?
On that note, it would be great if those samples would be kept updated!
It’s throwing:

InvalidOperationException: Burst failed to compile the given delegate: Void InstantiateEntitiesExecute(Unity.Entities.EntityComponentStore*, Unity.Entities.Entity*, Unity.Entities.Entity*, Int32)
   attribute: Unity.Burst.BurstCompileAttribute

from this line in EntityManagerChangeArchetype : InstantiateEntities = BurstCompiler.CompileFunctionPointer<InstantiateEntitiesDelegate>(InstantiateEntitiesExecute).Invoke;

2 things I saw:

  • They biggest improvement is to simply turn off shadows. Soft shadows for all the particles is quite heavy.
  • The TimedDestroySystem seems to be a bottleneck for the EndSimulationEntityCommandBufferSystem.

I can say that much
** Phyllotaxis with 100k cubes (vid) **
** Unity 2019.2 DOTS Physics Test: 343k Compounds Cubes **
Neither show sign of sweat, for such amount of rendered objects.
So definitely is doable. And these are recorded on 5 years old PC rig.

Is just recent changes to RenderMeshSystemV2, which causes main issues.
I believe, author of OP video have same issue, which wasn’t presented.

@Enzi which version of Burst are you using? Please could you try upgrading to 1.2.0-preview10 and see if the issue persists?

1 Like

Oh yeah, I missed I was on 1.1 and the package manager didn’t show an update icon.
I updated to 1.2 preview 10 and 11, but still, no luck.

These are the errors when I run it now:

Unexpected exception Burst.Options.OptionException: Unexpected arguments: `--is-for-function-pointer --managed-function-pointer=0x0000025FBD16A2C0`
  at Burst.Compiler.IL.Jit.JitCompilerService.Compile (Burst.Compiler.IL.Jit.JitCompilerService+CompileJob job) [0x0012a] in <3179d4839c86430ca331f2949f40ede5>:0

While compiling job: Unity.Entities.StructuralChange, Unity.Entities, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null::AddComponentEntitiesBatchExecute(Unity.Entities.EntityComponentStore*, Unity.Entities, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null|Unity.Collections.LowLevel.Unsafe.UnsafeList*, Unity.Collections, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null|System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
InvalidOperationException: Burst failed to compile the function pointer `Void AddComponentEntitiesBatchExecute(Unity.Entities.EntityComponentStore*, Unity.Collections.LowLevel.Unsafe.UnsafeList*, Int32)`
Unity.Burst.BurstCompiler.Compile[T] (T delegateObj, System.Boolean isFunctionPointer) (at Library/PackageCache/com.unity.burst@1.2.0-preview.10/Runtime/BurstCompiler.cs:160)
Unity.Burst.BurstCompiler.CompileFunctionPointer[T] (T delegateMethod) (at Library/PackageCache/com.unity.burst@1.2.0-preview.10/Runtime/BurstCompiler.cs:78)
Unity.Entities.StructuralChange.Initialize () (at Library/PackageCache/com.unity.entities@0.4.0-preview.10/Unity.Entities/EntityManagerChangeArchetype.cs:58)
Unity.Entities.EntityManager..ctor (Unity.Entities.World world) (at Library/PackageCache/com.unity.entities@0.4.0-preview.10/Unity.Entities/EntityManager.cs:163)
Unity.Entities.World..ctor (System.String name) (at Library/PackageCache/com.unity.entities@0.4.0-preview.10/Unity.Entities/World.cs:115)
Unity.Entities.DefaultWorldInitialization.Initialize (System.String defaultWorldName, System.Boolean editorWorld) (at Library/PackageCache/com.unity.entities@0.4.0-preview.10/Unity.Entities.Hybrid/Injection/DefaultWorldInitialization.cs:127)
Unity.Entities.AutomaticWorldBootstrap.Initialize () (at Library/PackageCache/com.unity.entities@0.4.0-preview.10/Unity.Entities.Hybrid/Injection/AutomaticWorldBootstrap.cs:15)

I’ve uploaded the project here: www.enzenebner.com/files/angrydots.rar
Not sure what’s going on. I never had such errors before and I just wanted to test the sample a little.

edit: Deleting the library folder and a full reimport has fixed the issue.
This behaviour is quite annoying TBH. Whatever is left when updating should be cleaned up.
The good thing is I get very acceptable frame timings (8ms in editor) even with a spread amount of like 50+.
So, updating will be worth it.

2 Likes

I think apart from the rendering, the problem is that ECS is not optimized for creating and destroying 100k entities within a fraction of a second. There’s a lot of overhead going on with EntityManager and chunk creation when doing structural changes and doing so is singlethreaded by design to make race conditions impossible. In a real usecase scenario you would probably try to keep/pool the entities and then hit a switch to reset them by iterating over them. This is where ECS really shines.

Creating and destroying 100k entities can be plenty fast. You just have to use the batched API’s.

In megacity we streamed in 200k entities and destroyed 200k entities in a single frame in less than 1ms.

6 Likes