Search Unity

Optimizing my SetFilter related situation

Discussion in 'Data Oriented Technology Stack' started by Xerioz, Jun 13, 2019.

  1. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    I'm using a special shared component data to categorize components into different groups, which would be processed depending on their sharedcomponentdata value.

    Previoulsy when ForEachFilter was available, the performance was great, but now with SetFilter I can't manage to achieve the same performance.

    "Get all values" and "Apply values" part are the slowest, even though my process jobs are way more complex and logic heavy.

    Code (CSharp):
    1.  
    2. EntityManager.GetAllUniqueSharedComponentData(uniques);
    3.  
    4. var DataReadOnly = new NativeArray<DataReadOnlyComponent>[uniques.Count];
    5. var DataWriteOnly = new NativeArray<DataWriteOnlyComponent>[uniques.Count];
    6.  
    7. // Get all values
    8. //-------------------------------------
    9. var jobHandles = new NativeArray<JobHandle>(uniques.Count, Allocator.Temp);
    10.  
    11. for (int x = 1; x < uniques.Count; x++)
    12. {
    13.     m_Group.SetFilter(uniques[x]);
    14.  
    15.     DataReadOnly[x]  = m_Group.ToComponentDataArray<DataReadOnlyComponent> (Allocator.TempJob, out var jhA);
    16.     DataWriteOnly[x] = m_Group.ToComponentDataArray<DataWriteOnlyComponent>(Allocator.TempJob, out var jhB);
    17.  
    18.     jobHandles[x] = JobHandle.CombineDependencies(jhA, jhB);
    19. }
    20.  
    21. JobHandle.CompleteAll(jobHandles);
    22.  
    23.  
    24. // Process values Jobs
    25. //-------------------------------------
    26. JobHandle lastHandle = default(JobHandle);
    27.  
    28. for (int x = 1; x < uniques.Count; x++)
    29. {
    30.     switch(uniques[x]){
    31.         case PROCESS_ONE_WAY:
    32.         {
    33.             // Instantiate new job using DataReadOnly[x] and DataWriteOnly[x] + additional components if necessary
    34.             lastHandle = new MyJob(DataReadOnly[x], DataWriteOnly[x]).Schedule(lastHandle);
    35.             break;
    36.         }
    37.         case PROCESS_DIFF_WAY:
    38.         case PROCESS_CRAZY_WAY:
    39.         //....
    40.     }
    41. }
    42. lastHandle.Complete();
    43.  
    44. // Apply values
    45. //-------------------------------------
    46. for (int x = 1; x < uniques.Count; x++)
    47. {
    48.     m_Group.SetFilter(uniques[x]);
    49.     m_Group.CopyFromComponentDataArray(DataWriteOnly[x]);
    50. }
    51.  
    52. // Dispose all
    53. //-------------------------------------
    54. for (int x = 1; x < uniques.Count; x++) {
    55.    DataReadOnly[x].Dispose();
    56.    DataWriteOnly[x].Dispose();
    57. }
    58.  
    I separated all the logic into diff parts because it was faster and helped me figure out where the performance loss was coming from, but it used to be in one loop.

    Can anyone help?
     
  2. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    Anyone?

    ForEachFilter was 10x faster for my case, since that function was removed, I assume it was due to performance reasons. But no matter how I format it, I still can't achieve the same performance as I did with ForEachFilter. This is really frustrating.
     
  3. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    You can use Entities.ForEach and IJobForeach with a custom EntityQuery. The custom EntityQuery can be set to have any filter you like when you run those two foreaches.

    Entities.ForEach is recommended for main thread work.
    IJobForeach is recommended for work that can run on jobs.
     
  4. Xerioz

    Xerioz

    Joined:
    Aug 13, 2013
    Posts:
    104
    I used to have Entities.ForEach until I transformed the class into JobComponentSystem, I don't think the performance was any better.

    I ended up solving this using chunk iteration. Creating jobs per chunk seems to work much better than my initial approach.
     
  5. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    As general rule if you care about performance IJobForEach is the recommended approach. It is performant and simple. Chunk iteration is a more low-level concept.