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