Search Unity

looking forward to that ECS :D

Discussion in 'Data Oriented Technology Stack' started by laurentlavigne, Jan 22, 2018.

  1. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    2,015
    All that blue, 8ms for 6000 objects just moving and reading off a vector field, a good candidate for ECS I think.
    What do you guys have that also hungers for ECS?
     
  2. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    591
    Mildly complicated, robust platformer collisions in 3d. The ability to process both the raycasts/spherecasts/Computepenetration calls, as well as process all of the other related logic across multiple threads, including constraint handling for splines and other designer-authored spatial distortions.

    Also the accompanying AI logic and dynamic re-pathing that can account for moving platforms.

    At locked 60fps, while recording input and game state for immediate replay (at least a few seconds to maybe a minute of gameplay).

    Edit - I actually had an input journaling prototype made in Entitas that could store an arbitrary ring buffer of input, then play it back from a file, but I'm waiting to see how the new input stuff plays out before going down that rabbit hole again.
     
    laurentlavigne likes this.
  3. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,063
    I will be working on an ECS-ready networked game framework built on top of the UNET LLAPI. I find that the idea of "component systems" fits networking beautifully. Instead of working like the HLAPI where all components are responsible for sending a message that syncs their vars, here each system would be responsible for the syncing of all of their components at once (with bitmasks to trim out the unneccessary stuff). This will be extremely simple to accomplish with the ECS and should save tons of CPU time and bandwidth when compared to the per-component approach.

    Another advantage of this approach is that since all networking is now handled by "networking systems", your game classes will be the exact same regardless of if you're online or not. They won't need to inherit from some sort of "NetworkBehaviour" or have conditions like "isOnline" or "isServer". It's all handled externally

    ...not that I can't already do an equivalent of this right now without the ECS, but the ECS will make a system like this really clean and beautiful, and will save me tons of work. So I'd rather work on my other projects while waiting for it to be released

    And then I will also look into the possibility of jobifying all the syncing logic

    I'm guessing that's more related to the Job system rather than the ECS, but I 100% agree. Can't wait for all of the Physics API to be jobifyable
     
    Last edited: Jan 23, 2018
  4. AdamSingle

    AdamSingle

    Joined:
    Apr 18, 2013
    Posts:
    16
    I was hoping the ECS would drop in beta 4, but it seems not sadly
     
  5. X301

    X301

    Joined:
    Jan 24, 2013
    Posts:
    108
    I'm waiting for ECS so for my multiple floor grid based pathfinding system. Want to make a xcom like prototype game.
     
  6. X301

    X301

    Joined:
    Jan 24, 2013
    Posts:
    108
    Are you using gpu instancing? I just got it working with my pallet swapping shader and I was impressed. You could use a material properly block and have all those blocks have there own color while having them all batched together. I think it batches every 1000 objects so you would have 6 draw calls I believe. Could be wrong.

    IMG_20180126_142835_01.jpg
     
    Last edited: Jan 29, 2018
  7. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    2,015
    Rendering is ok, it's the amount of monos that I've got running.
     
  8. X301

    X301

    Joined:
    Jan 24, 2013
    Posts:
    108
  9. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    2,015
    GameDevCouple_I likes this.
  10. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    199
    Can't say the same. Setting struct data is slow because of compiler constraints and no direct ref. No way around it right now. Everything else performs as expected. There was useless overhead in early versions but that's gone.

    I have a factorio transport belt simulator with 1million items running at 10ms on a single core with BrokenBrickECS and same in Svelto.ECS. Svelto can multi-thread it with around 7ms.
    Most of the time is wasted with expensive setting of transform.positions and rendering in my case.

    Not sure where you had problems. My experience with it was really good. I've finished most of the porting of my current OOP project and I had no issues. To the contrary. ECS is great!

    Also important, it shouldn't be too different when Unity releases their ECS.
     
  11. X301

    X301

    Joined:
    Jan 24, 2013
    Posts:
    108
    I used it for my grid pathfinding and rendering grid cells on the map took 1-2ms(computer runs slower when it's on more than 20 minutes so I get throttling on my couch because I have a broken fan) on a map of 100x5x100. I did not run into much issues with with position because I held my positions in vector3 array and it only changes when stairs and walls move around or get destroyed. I must say I don't like using structs. Not really sure why they are apparently faster but you need to pass by values which is shower than passing by reference if I'm not mistaken.
     
  12. rastlin

    rastlin

    Joined:
    Jun 5, 2017
    Posts:
    100
    That's the common misunderstanding from the author, structures are not faster than classes, in fact they are generally slower if coded right. The only advantage is they reduce GC.Alloc, which in proper solution is resolved by pooling class components. If anything, structures will increase memory footprint of you solution, since they are always pass by value, which essentially duplicates it many times instead of duplicating just the pointer. And they are extremely error prone and funky to work with.
     
  13. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,063
    You can pass structs by ref, though:
    Code (CSharp):
    1. public void DoSomethingWithStruct(ref MyStruct struct)
    2. {
    3. }
    Where structs really become useful is that they are contiguous in memory. So if you're iterating over a structs list, you'll have few cache misses compared to iterating over a class list
     
    Last edited: Jan 27, 2018
    Peter77 likes this.
  14. Creepgin

    Creepgin

    Joined:
    Dec 14, 2010
    Posts:
    262
    I don't think the ECS will be built-in. When it's ready, they will make the git repo public and write a blog post about it.

    Just speculating...
     
    AdamSingle likes this.
  15. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,063
    Joachim said this week in another thread that they are aiming for february for the ECS release, and it'll be on github
     
    Creepgin likes this.
  16. rastlin

    rastlin

    Joined:
    Jun 5, 2017
    Posts:
    100
    I don't think cache locality is a concern in code related to any interactions with ECS, as there are mountains of different other issues which can contribute way more to the performance, than the fact that you have classes instead of structs in your ECS. This also applies to the situation when you have a list with identical structs, which again is rarely the case in ECS interactions, since the point is to have many different structs.

    Everything has it's uses and appliances where it shines, and I'm not convinced ECS is such a place for structures.
     
  17. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    4,265
    Well, will see how they implement the ECS and you can actually measure if you're right or not. :)
    In general cache hits and misses are pretty much concerns when it comes to performance. Although you're right there are implementations when something else is more of a concern. But it does not mean that you're right in general, it just means that the implementation is, well, less than ideal.
     
  18. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,355
    Actually the reason lists/arrays of structs are good on the cache is because they are not allocated on the stack in that case. They are allocated on the heap as part of the list.

    L1/L2 cache optimization is generally not going to pay off just trying to do it everywhere. L2 caches on modern cpu's are big, so you often end up with a lot of your game data there anyways. It pays to optimize for that when you can not saying it's not, but you can spend hours doing that all over for gains that aren't even measurable.
     
  19. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    4,265
    So you're saying that you can fit 50-60000 objects in the L1/L2 caches fully in order to not to be needed to load into it from the RAM?
    And secondly, you won't spend hours to optimize things if you choose this system to use they introduced, you initially will write the most important things this way. So I really don't understand the resentment here. If they put it out and does not work or everyone will be capable to do the same thing with gameobjects and classes on the OOP way with the same performance, I will pick up the torch and the fork as well. But until then I will give them the benefit of the doubt and will wait for the solution and judge when they fully delivered something.
     
  20. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,355
    I wasn't even talking about ECS there. On the caching my point was that it doesn't pay to optimize what is inherently a small subset of the data you are working with. That's all.
     
  21. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    This is simply not true. Classes are allocated in .NET and make no gurantees about memory layout. As a result iterating over an array of classes and fetching one value from it, is slower than doing the same with a tightly packed struct.

    Additionally classes also have an 16 byte header for VTables. So especially for small structs / classes that can be an overwhelming amount of wasted memory.

    On all modern CPU's bandwidth is more important than instruction count. Now in .NET this is less visible because generally the code isn't as optimized as hand written code.

    With our burst compiler the difference between pointer lookup vs linear iteration in an array is massive, because the generated instructions are quite optimal, using SIMD etc, so memory layout becomes the clear bottleneck.

    In .NET there is also the fact that by default structs are passed by value as opposed to by ref, so as a user it is pretty easy to incur additional overhead when passing it to a function. Naturally thats where passing by ref comes handy. Additionally in C# 7 there is support for ref returns which solves the biggest problem with structs in terms of usability in .NET.

    For ECS we will be using C# 7.

    Also in burst passing by ref vs value doesn't really matter because we will optimize the code in such a way that it doesn't matter.
     
  22. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    Linear memory access & SIMD capable code is maybe not the most important issue when getting to decent performance, but if you want great or optimal performance it is absolutely necessary.

    One key goal for ECS is to provide performance by default. By that we mean making optimal performance (Perfect linear memory access + SIMD code, competitive with handwritten SIMD intrinsics in C++ or ASM)... making that easy to do.

    I think this talk will help understand what we are trying to do:
     
  23. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    459
    so, can I assume that either 4.6 runtime will be stable or the compiler has "-langversion:7" enabled by default? (tuples :D )

    btw how will the ecs handle tightly packing the data with the fact that different system requires different components?
    e.g. if the rendering system requires transform and renderer, and the physics system requires transform and rigidbody, and there are entities with any combinations, how do you pack the transforms, for example? do you copy all the data for each running system? do you leave 'holes' for entities without some components?
    how does it scale wrt:
    - number of entities in scene
    - number of running systems
    - number of different component types
    - adding/removing entities
    - adding/removing components from an existing entity
    - enabling/disabling systems at runtime (if allowed)
     
  24. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    84
    @M_R I think you misunderstood "tightly packing". Each component array will be separate thing in separate places in memory, but array of structs will be one huge chunk of memory which you can easily iterate comparing to class objects which will be in random places in memory.
     
  25. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    459
    then
    1) if a system needs 2 components (e.g. transform + rigidbody) and you are unlucky, the transform for an entity will collide in cache with the rigidbody of the same (or nearby) entity, meaning 100% cache miss
    2) if my system needs transform + renderer and not all transforms also have a renderer, how do I relate components of the same entity? in the code snippets shown in the video, a system was iterating once and using the same index in both component arrays (e.g. at 57:59 with "MinionVelocity" and "PositionAndRotation").
    a global array of all the transforms in scene will not have the same length or index of the renderer array or rigidbodies or custom components etc...
     
  26. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    4,265
    1; this is why the injected nativearrays will be super-lightweight
    2; As far as I understand they don't expect us to write global jobs. At 48:02 Joachim talks about the inject tuples, every job will get any objects which has all of the injections you give, therefore the nativearrays will always have the same length and order.
     
    Krajca likes this.
  27. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    459
    therefore it requires copying all the relevant data for each system.
    e.g. if you have 5 systems that want transform, you need 5 copies of each transform in memory, each one together with the other components for the system.
    also, a typical system would loop through its entities and do stuff with all (relevant) components of the same entities together, so it would be better for the cache to have its packed array like [A,B,A,B,A,B,A,B,A,B,...] (where A and B are the component types). you can do that in native C/C++ code (something like malloc(n*(sizeof(A)+sizeof(B))) and be VERY careful with the pointers...)
     
  28. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    84
    I think that's the case: each system will have its own arrays of things that are needed for work its work
     
  29. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    764
    I'm looking forward to finding out how to use ECS to replace pooling systems. Generally the things I pool in games are:

    Audio Sources
    Enemies
    Particle Systems

    Sometimes these objects have complex hierarchies with many components at various levels. Maybe I haven't paid enough attention in the videos, but it looks like replacing a pooling system with ECS is really only viable on certain object configurations, like: GameObject with a Transform, MeshFilter, MeshRenderer. Maybe as time goes on more Unity components will enter the ECS world...

    Or, everything is possible and I have no idea what I'm talking about!
     
  30. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    We have the concept of an archetype. (Set of components) We group entities of similar archetype together. Components of the same type in the same archetype are laid one one after another in a chunk (64kb block of memory containing all component data)

    As a result we gurantee linear iteration over component data. Also there is no overhead to having more / less components on an entity.

    When entities get destroyed we move the component data of another entity in place. Effectively we continously move data around. The cost of doing that in game objects was mostly the events and generic memory allocators. Those costs are completely gone in ECS. Which is why it is so much faster.
     
    IsaiahKelly likes this.
  31. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    No. See above, the data is organized by archetype. Systems reference data and have faster iteration. But there is a single piece of data for each component. The overhead for an entity is a fixed 16 bytes on top of the actual component data. There is no per component overhead, which still blows my mind.
     
    Krajca likes this.
  32. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    Thats the idea, as a starting point the ECS only entities world is pretty empty. We have a super simple instance renderer, and some sample code. No physics, no audio, no particle systems. It will take time to build all that.

    Thats why mix & match is so important, so you you can use ComponentSystem to talk to existing game objects, MonoBehaviours, Rigidbodies or AudioSource. So you can write main thread ComponentSystem code to talk to a rigidbody or a particle system or audio source. It's not the 100x speedups we dream about but it gets you started with smaller perf gains.

    But if you want to go all in with super fast EntityManager instantiation, jobified access to the components etc, that requires those sub-systems to have new IComponentData & Systems to be rebuilt completely for that ECS world. Thats clearly the end-goal but getting to that point will take quite a long time. Essentially it requires rebuilding those systems from scratch.

    In practice the things you want at scale, often don't require a huge amount of features and those features you want to tightly control. Thats effectively what we showed in the Unity Austin demo.

    We used jobified Physics.Raycast & new Low Level Navmesh query api's but all other code for dealing with the minions, arrows etc, was all jobified C# code specifically written for them demo.
     
  33. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    84
    Oh yeah it seems better to keep arrays of archetype than arrays of components.
     
  34. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    2,015
    Assuming you won't release the early ECS on thursday, could you share some code snippets of this mix and match? I plan on using your ECS so I don't want to over think the stuff I'm currently doing.
     
  35. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    232
    Will there be some preview of ECS available during 2018.1 beta?
     
    JakubSmaga and Krajca like this.
  36. GameDevCouple_I

    GameDevCouple_I

    Joined:
    Oct 5, 2013
    Posts:
    1,847
    Yeah, even though nothing is set in stone, it would be great to get some code examples of what it is like currently so we can at least begin designing systems in a way that can be remade for ECS a bit easier.
     
    recursive and Krajca like this.
  37. Ziboo

    Ziboo

    Joined:
    Aug 30, 2011
    Posts:
    290
    I used Entitas for some time, and I loved their debugging system. See how much systems takes and ability to toggle them on/off. I guess Unity will use the Profiler for performance.
    Could be nice to have a sperate window somewhere to see systems running and be able to toggle them.

    I'm also wondering a lot how we will build prefabs with this new ECS system.
    I don't want artist to add 30 components to a prefab just to make it a simple Enemy Class.
    Entitas has a template system. hopefully Unity though about that.
     
  38. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    84
    @Ziboo what's wrong with unity prefabs?
     
  39. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    25,445
    Right well I'll trust whatever @Joachim_Ante decides because his brain is far more optimised than mine. My only thought is I am surprised it is C# 7 code on github. This means that Unity is very confident in IL2CPP.
     
  40. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    4,005
    Can you elaborate?
     
  41. GameDevCouple_I

    GameDevCouple_I

    Joined:
    Oct 5, 2013
    Posts:
    1,847
    essentially means they are putting the IL2CPP before mono, which imo is a good and sensible thing.
     
  42. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    2,015
    Instantiating is slow as F*** so you need to pool everything and their grandma, once the object is in the scene there is an overhead. All that you don't feel on 100 objects with scripts but when you run 10k agents it hurts.
     
  43. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    84
    @laurentlavigne did you see this video?
    It seems that instantiating will be reworked.
     
  44. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    2,015
    which time in the video?
     
  45. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    84
     
  46. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    2,015
    only for entities (en-titties, i wonder if it'll get auto-censored...)
    (edit: not auto)
     
  47. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    84
    Isn't it be the way from now on?