Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[SOLVED] Persistent / Async Unity Job only possible if entities package installed

Discussion in 'Entity Component System' started by meanmonkey, Dec 12, 2018.

  1. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    Unity 2018.2.18f1
    Jobs 0.0.7-preview.5
    Collections 0.0.9-preview.10
    Mathematics 0.0.12-preview.19
    Entities 0.0.12-preview.21

    I'm using serveral persistent unity jobs for async background loading. Basically it looks like this:

    Code (CSharp):
    1. private struct BackGroundWorkerJob : IJob
    2.         {
    3.             public void Execute()
    4.             {
    5.                while (Root.TestJobContainer.backGroundWorkerJobIsActive)
    6.                {
    7.                     Root.TestJobContainer.backGroundWorkerJobWaitHandle.WaitOne();
    8.  
    9.                     // Do stuff with system.concurrent queue
    10.                }
    11.             }
    12.         }
    As you can see, I invoke the job via System.Threading.EventWaitHandle. I'm using object references in here but I do not need any burst for the background loader so this doesn't matter to me at all.

    This works fine in my working project. But when I did some tests in a separate unity project, I realized this only will work (not working = no execute) if the entities package is installed. Which isn't acutally a problem to me as I am using the entities package, but I still think this shouldn't be, as there is no strict dependency between jobs and entities.

    To be clear: The job still works fine non-persistent / when using .Complete() each frame, but as I said I need it to be persistent / frame independent.

    EDIT: Ok I just realized the warning (not an error and independetly from entities package):
    Internal: JobTempAlloc has allocations that are more than 4 frames old - this is not allowed and likely a leak
    So I do fear now unity jobs are not allowed to be persistent at all? Which would be a real bummer to me as my project depends on background loading and accessing (readonly) nativearrays.

    EDIT 2: As this thread states: https://forum.unity.com/threads/job...tions-that-are-more-than-4-frames-old.513124/ they plan to fix the warning, so this is a release to me, unity jobs will support async runs. Still I wonder about the entities package dependency...
     
    Last edited: Dec 12, 2018
  2. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    >Internal: JobTempAlloc has allocations that are more than 4 frames old - this is not allowed and likely a leak
    It's a warning that can be ignored for the time being. In this particular case it just holds on to temp job memory for longer than expected.

    We are planning to add flags to job scheduler to make the jobs use the right type of allocator to get rid of the warning.
     
    meanmonkey likes this.
  3. meanmonkey

    meanmonkey

    Joined:
    Nov 13, 2014
    Posts:
    148
    Thanks @Joachim_Ante for pointing that out!

    I can set this topic to solved, even if I have no explanation why my last solution was working with entities package, but not without. To be fair it was a bit "hacky" and not as intended by unity.

    My conclusion: if you use a unity job and keep it alive with a while(true) loop and invoke it with a System.Threading.EventWaitHandle, you will run into problems: 1.) It won't execute unless you have the entities package installed (for whatever reason, seems to be an odd coincidence) 2.) The editor profiler will freeze (I suppose because the profiler is waiting for jobs to complete but they never do, this was the reason I started testing in another project)

    My solution: Doing it the unity way, got rid of the while(true) loop and waithandle, replaced it with

    if(jobhandle.isComplete) // do not confuse with .Complete()
    {
    jobHandle = job.Schedule();
    }

    And do not forget to run joHandle.Complete() when shutting down.

    I have to point out that scheduling each frame is quite expensive in the editor mode (half of the framerate), I think due to security checks. However it is working normal in the built version. If you want to avoid the peformance loss each frame in the editor you should do an extra check if there is anything to do at all (e.g. concurrentQueue.Count > 0), or invoke on demand from the queueing method, if feasable.

    EDIT: As I figured out to complete each async job, you'll have to do add .Complete() within the boolean check.

    if(jobhandle.isComplete)
    {
    jobHandle.Complete()
    jobHandle = job.Schedule();
    }
     
    Last edited: Dec 13, 2018