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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question How big is the impact of not caching type handles?

Discussion in 'Entity Component System' started by davenirline, Jun 24, 2022.

  1. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    948
    I didn't know that you can cache type handles in OnCreate() then just call Update() on them prior to usage in OnUpdate() until it was mentioned in the latest change log. We are very used to just calling the Get*TypeHandle() when scheduling jobs in OnUpdate(). This is going to be a huge refactor but maybe we don't have to this? Our game is doing fine without the caching but since the change log says that it's more efficient to do so, I'm having doubts.
     
  2. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    944
    If it ain't broken don't fix it.
    If you have no performance issue don't worry about it IMO.
    Just add it to your best practices for your next projects/systems.
     
    elliotc-unity likes this.
  3. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    This mostly helps in situations where you have lots of overhead from lots of systems but need them to be managed SystemBase systems. If it is not a problem, don't worry about it.
     
    bb8_1, Occuros, elliotc-unity and 2 others like this.
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,647
    I can give you some numbers, on a slower platform (xbox one) in a system with a lot of dependencies (25+) main thread went from 1.35 to 0.67ms caching them.

    The real cost is every call iterates an unsafe list of all dependencies to check to see if it needs to be added. This is slow once your dependency count gets high.

    On a system with only a couple of dependencies benefit is small, but under the right circumstances it's pretty huge.
     
    bb8_1, WAYNGames, mikaelK and 3 others like this.
  5. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    948
    Thanks. That's good information.

    What do you mean by "dependency" here? Is it the chaining of this.Dependency = job.Schedule(..., this.Dependency)? Or is it something else?
     
  6. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,647
    Dependencies that have been added to the system.

    All dependencies in a query but also all calls to GetComponentTypeHandle, GetComponentFromEntity, (and buffer equiv etc) add a dependency to the system.
     
    bb8_1 and davenirline like this.
  7. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,647
    Code (CSharp):
    1.         public ComponentTypeHandle<T> GetComponentTypeHandle<T>(bool isReadOnly = false) where T : struct, IComponentData
    2.         {
    3.             AddReaderWriter(isReadOnly ? ComponentType.ReadOnly<T>() : ComponentType.ReadWrite<T>());
    4.             return EntityManager.GetComponentTypeHandle<T>(isReadOnly);
    5.         }
    6.  
    > AddReaderWriter

    Code (CSharp):
    1.  
    2. public static bool Add(ComponentType type, ref UnsafeList<int> reading, ref UnsafeList<int> writing)
    3. {
    4.     Assert.IsFalse(type == ComponentType.ReadWrite<Entity>());
    5.  
    6.     if (type.IsZeroSized)
    7.         return false;
    8.  
    9.     if (type.AccessModeType == ComponentType.AccessMode.ReadOnly)
    10.         return AddReaderTypeIndex(type.TypeIndex, ref reading, ref writing);
    11.     else
    12.         return AddWriterTypeIndex(type.TypeIndex, ref reading, ref writing);
    13. }
    14.  
    15. public static bool AddReaderTypeIndex(int typeIndex, ref UnsafeList<int> reading, ref UnsafeList<int> writing)
    16. {
    17.     if (reading.Contains(typeIndex))
    18.         return false;
    19.     if (writing.Contains(typeIndex))
    20.         return false;
    21.  
    22.     reading.Add(typeIndex);
    23.     return true;
    24. }
    25.  
    26. public static bool AddWriterTypeIndex(int typeIndex, ref UnsafeList<int> reading, ref UnsafeList<int> writing)
    27. {
    28.     if (writing.Contains(typeIndex))
    29.         return false;
    30.  
    31.     var readingIndex = reading.IndexOf(typeIndex);
    32.     if (readingIndex != -1)
    33.         reading.RemoveAtSwapBack(readingIndex);
    34.  
    35.     writing.Add(typeIndex);
    36.     return true;
    37. }
    38.  
    Basically calling this every frame for every Xhandletype/getXdata you do in your update (this runs must faster in burst though btw)
     
    davenirline, Anthiese and bb8_1 like this.
  8. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    801
    So for lambda based jobs I assume this is not automatic?