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

Calling complete before returning JobHandle in JobComponentSystem causing performance issues (?).

Discussion in 'Entity Component System' started by Mr-Mechanical, Jan 8, 2019.

  1. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    I've been dissecting my code to address performance issues lately and I've recently found this to be a problem. How should I go about avoiding this performance hitch?

    Code (CSharp):
    1. protected override JobHandle OnUpdate(JobHandle inputDeps)
    2. {
    3.        SomeJob someIJobParallelForJob = new SomeJob();
    4. //job is populated here (not shown)
    5. //note that the batch size is extremely small (1) because there will be very few items to iterate over.
    6.        JobHandle jobHandle = someIJobParallelForJob.Schedule(someIJobParallelForJob.nativeArray.Length, 1, inputDeps);
    7.        jobHandle.Complete(); //<- disabling this line of code fixes performance problem
    8. //When calling Complete() before returning handle my fps goes from 60 to 45.
    9. //calling complete is necassary here because I will eventually need to use the nativearray from someIJobParallelForJob for another job here in OnUpdate
    10.  
    11.        return jobHandle;
    12. }
    Thank you in advance. Feedback is greatly appreciated.
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,655
    It's not a problem, it's expected, you put inputDeps as dependency in to job and your Complete, complete ALL jobs in chain from other systems populated in this inputDeps if work in your job hasn't race conditions with other systems in chain, just not put dependency, do stuff in this job and call Complete, and just use inputDeps in other job if it required.
     
    Last edited: Jan 9, 2019
  3. Attatekjir

    Attatekjir

    Joined:
    Sep 17, 2018
    Posts:
    23
    You could call JobHandle.ScheduleBatchedJobs() when having scheduled all your job's "inputDeps" earlier in the update cycle and somehow manage that they are done in time when you reach your small job.
     
  4. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    I've noticed that removing ALL code except this replicates my performance issue. Note I am testing on a device with only 2 cores.
    Code (CSharp):
    1. protected override JobHandle OnUpdate(JobHandle inputDeps) {
    2.       inputDeps.Complete();
    3.       return inputDeps;
    4. }
    I need to access a native array from a job so looks like I have to call complete to pass the container onto another job but I'd be interested in any potential alternatives.

    I am fascinated by your mention of JobHandle.ScheduleBatchedJobs(), but to be honest I am still confused after looking at docs on how to use it properly.

    Thank you for the feedback so far.
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,648
    Why does that require completing the job? Simply passing that job handle to the next job as a dependency would work.
     
  6. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,655
     
  7. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,655
    I say him that but he not read my answer :D
     
  8. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    You're right. I misspoke. Actually, I have this Concurrent NativeQueue that is populated with a job. But I need to dequeue on main thread to convert to nativearray so that the results can be processed in parallel in another job. So right now that's why I have to call complete. But I like this idea of just passing dependencies to avoid using complete altogether, but I don't know how to 100% completely jobify converting concurrent nativequeue to nativearray tho. I am not sure it's possible because you still have to initialize container on main thread. I'd be interesting in your guys thoughts about this. Thanks.
     
  9. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,648
    If you can't figure out size of queue/array from the size of the chunk,

    use a list instead of an array?
     
  10. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    I am having this problem again when using GetKeyArray with NativeMultiHashMap. I have to call Complete on the previous job for GetKeyArray and this causes massive performance issues.

    Is anyone else having problems with calling complete in the middle of a sequence of jobs? I have experienced this with 2 different machines.

    Thanks, advice is appreciated.
     
  11. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,993
    It sounds like your issue is that your second system doesn't realize it depends on the jobs of the first system. This happens because the dependency tracking between systems is based on types registered with ECS (IComponentData for example). So you need to either manually pass the returned JobHandles from your first system to your second system and complete them there, or use some sort of tag component to trick the dependency system. That way, the jobs won't be forced to complete until as late as possible.
     
  12. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,648
    Show us what you're trying to do?

    There are many cases you have to call Complete in the middle of a job sequence because you have to do work on main thread, RenderMeshSystem, TransformSystem etc do this.

    While you should avoid it where possible it shouldn't kill performance. It's still doing the same amount of work overall. It usually just reduces your max throughput a bit by being slightly less optimal.
     
    Mr-Mechanical likes this.
  13. Mr-Mechanical

    Mr-Mechanical

    Joined:
    May 31, 2015
    Posts:
    507
    Thanks for your interest. The scheduling code is exactly what you'd expect and is identical to what is above. Unfortunately, I have had this exact same problem with completely different things.

    Right now I'm trying to process Keys from a hashmap after writing to it so I have to call complete to use GetKeyArray.
     
  14. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,131
    I have not tried this or investigated much and I am only guessing here. It seems you are able to call GetKeyArray in a job (which allocates a native array), so once they allow the allocation / disposal of native arrays in a job, it might work without main thread (if you have the dependencies right). If you are lucky the answer is to just wait...
     
    Mr-Mechanical likes this.