Search Unity

Barriers best practices

Discussion in 'Entity Component System' started by kork, Jan 23, 2019.

  1. kork

    kork

    Joined:
    Jul 14, 2009
    Posts:
    280
    Suppose you have a lot of
    JobComponentSystem
    s. Now what you can do is either create one barrier for each of those or have a shared barrier which all or most of them use. Since every barrier system adds overhead (it's another system to run that slices of 0.02ms off your budget), I wonder what the best practices are regarding barriers. Am I overly concerned about the overhead and having hundreds of barrier systems isn't really a problem or should you try to share barriers where possible?

    I fear this is one of these "it depends" questions, but I really would like to know how you use them and if you found that having too many barriers is a problem.
     
    Antypodish likes this.
  2. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    You should try to reduce the amount of barriers!

    The best you could do is:
    • Define for each archetype a system which is responsible for entity creation of that archetype.
      • You can expose a method for qeueing infos about entity creation, which can be used by other systems
      • This is also faster than a barrier, because of the use of batched API.
    • You can do the same for destruction

    Keep in mind that each Barrier is a hard synchpoint for all jobs that acts on the same types of components.

    There are a couple of discussions in this forum about it.
    Just use the Search function ;)
     
  3. kork

    kork

    Joined:
    Jul 14, 2009
    Posts:
    280
    Well I'm not only talking about creation/destruction of entities. Basically every job that just modifies some components will need to have a command buffer and hence need to have a barrier system where this command buffer comes from and where the commands are eventually executed. Regarding the approach you suggested for creating/deleting entities - do you have an example of how this would look?

    I tried searching for "barrier systems", "barrier overhead", but nothing conclusive came up. Could you recommend some keywords for finding these topics?
     
  4. RecursiveEclipse

    RecursiveEclipse

    Joined:
    Sep 6, 2018
    Posts:
    298
    Some general notes:

    You don't have to create your own barrier, you can inject the already existing EndFrameBarrier if you don't need a specific sync point and everything will be done at the end of the frame. You only need barriers if you Add/Remove components or destroy/create entities, not modifying components(not clear if you knew that but it's an important distinction). You can use Burst when you use DestroyEntity to speed things up, but not the others(because they use static right now I believe). I think you can create/modify separate entities in the main thread while iterating over others, so long as you don't modify the chunk you're iterating over(not quite sure about this).

    I'm curious to see an example of this, particularly about the batched API. I know about the main thread EntityManager NativeArray overload, so would we create some number of entities and then use jobs to set them up?
     
    Last edited: Jan 24, 2019
    Antypodish, kork and GilCat like this.
  5. kork

    kork

    Joined:
    Jul 14, 2009
    Posts:
    280

    I see. So you only use barriers if you need to specifically ensure that a command buffer is played back before another system runs, otherwise you can just use
    EndFrameBarrier
    and go your merry way.

    Yes, I was being unspecific. With "modifying components" I more specifically meant modifying the set of components that is attached to an entity. I should have used "add/remove components". You can directly modify components by using the
    ref
    parameters given to the job:

    Code (CSharp):
    1. public void Execute(Entity entity, int index,  ref MyComponent myComponent)
    2. {
    3.          myComponent.Value = 381;
    4. }
    And this change will be effective immediately. It also doesn't reorganize the chunks, hence it is safe to do it in a job.

    I tried this with mixed success. Sometimes it works sometimes it doesn't. My theory is that when you create new entities or add/remove components some chunks will be reorganized depending on how much is in them. And if you're unlucky, the newly created entities are added to the same chunk you're currently iterating over. And then your code breaks. This is something that you have no control over (at least I'm not aware of any possibility to control this). Therefore even on the main thread I use
    PostUpdateCommands
    wherever possible. I don't like my code to suddenly break when I change a thing elsewhere and also i try to avoid to cleverly use side effects as this tends to bite me in the long run. After all performance is important but maintainability is equally important to me.

    @Spy-Shifty - do you have a code example showing how you do this?
     
  6. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    https://forum.unity.com/threads/batch-entitycommandbuffer.593569/ read @tertle 's post related on @5argon article

    Just performance diff between batched approach and unity barriers. (from linked thread)
    upload_2019-1-24_10-0-38.png
     
  7. RecursiveEclipse

    RecursiveEclipse

    Joined:
    Sep 6, 2018
    Posts:
    298
    Yes. You could also use another system's(your own) barrier if you wanted.

    Yeah, it sounds like a bad idea in practice, just me rambling a bit.
     
    Last edited: Jan 24, 2019