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

Best Way To Deallocate Memory For Ecs Jobs

Discussion in 'Entity Component System' started by james_unity988, Apr 10, 2019.

  1. james_unity988

    james_unity988

    Joined:
    Aug 10, 2018
    Posts:
    71
    Hi there,

    I would like to know what is the preferred way to deallocate memory. In my case, these are NativeArrays which have been created per-frame then passed to various jobs to complete asynchronously. I am using
    JobComponentSystem, passing the inputDeps into my first job and returning the final job of the process.

    The way I look at it, I have two options:

    1. At the beginning of OnUpdate, Complete() the job and deallocate for the next execution.
    2. Create a job in the last step of the process to deallocate the memory.

    Let me know if I'm on the right track or not.

    Thanks
     
  2. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    I'm leaning towards option 2. I have actually created a generic job purely to deallocate NativeArrays after I'm done using them.
     
  3. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    NativeArray supports the [DeallocateOnJobCompletion]
    this should be attached to the member of the last job accessing the array (write order) or create a seperate job for that...
     
  4. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    789
    [DeallocateOnJobCompletion] works fine with NativeArray, but not with others Collections (NativeList)
    In one in my cases i created a persistent NativeList as a member oft the System and clear the list before reusing.
     
    Abbrew likes this.
  5. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Yep thats correct.

    If you use persistent collections, you have to save the JobHandle from the last frame in a member and call Complete() before clearing it. Otherwise you will have a violation...
     
  6. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    789
    if you use JobComponentSystem, you don't need to complete() by yourself.
     
  7. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Like Spy-Shifty said if u have to deallocate collections u should call Complete() on job that use your collection.
     
  8. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    789
    On JobComponentSystem you return the handle, and its complete on the end of the frame:
    An exemple from my code:

    Code (CSharp):
    1. protected override JobHandle OnUpdate(JobHandle inputDependencies)
    2. {
    3.     var nodesChunks = this.nodesQuery.CreateArchetypeChunkArray(Allocator.TempJob);
    4.     var returnHandle = inputDependencies;
    5.     if (nodesChunks.Length > 0)
    6.     {
    7.         var entityType = GetArchetypeChunkEntityType();
    8.         var nodeType = GetArchetypeChunkComponentType<Node>(true);
    9.         var nodeParentType = GetArchetypeChunkComponentType<NodeParent>();
    10.         this.resetedNodes.Clear(); // <- persistent NativeList
    11.  
    12.         var filterJob = new FilterNodes()
    13.         {
    14.             Chunks = nodesChunks,
    15.             ResetedNodes = this.resetedNodes,
    16.             NodeType = nodeType,
    17.             NodeParentType = nodeParentType,
    18.             EntityType = entityType
    19.         };
    20.         var filterJobHandle = filterJob.Schedule(inputDependencies);
    21.  
    22.         var calculateJob = new CalculateNodes()
    23.         {
    24.             ResetedNodes = this.resetedNodes.AsDeferredJobArray(),
    25.             EntityCommand = this.entityCommandBufferSystem.CreateCommandBuffer()
    26.         };
    27.         returnHandle = calculateJob.Schedule(filterJobHandle);
    28.         this.entityCommandBufferSystem.AddJobHandleForProducer(returnHandle);
    29.     }
    30.     else
    31.     {
    32.         nodesChunks.Dispose();
    33.     }  
    34.     return returnHandle;
    35. }
    36.  
    edit: the filter job has [DeallocateOnJobCompletion] on the chunk array.
     
  9. james_unity988

    james_unity988

    Joined:
    Aug 10, 2018
    Posts:
    71
    Thanks for the great feedback everyone!

    One thing I noticed - even after deallocating the memory, I still get warnings that the TempJob native containers are living longer than 4 frames. I'm not getting the errors with the stack traces, just warnings. But if the jobs are Complete()'d at the end of the frame, this shouldn't happen right?
     
  10. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    789
  11. james_unity988

    james_unity988

    Joined:
    Aug 10, 2018
    Posts:
    71
    yep, that's the issue! So I'm not crazy then! I like not being crazy! :)
     
  12. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    I'd like to revive this thread. How is this done now? I'm still using persisting collection and clearing them before firing jobs.
     
  13. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    [DeallocateOnJobCompletion] still works. Dispose(JobHandle inputDeps) is another option which decouples the Dispose from a job. And of course clearing a persisting collection can still be the best option if you can make that work and the collection is large.
     
    Thefolle likes this.
  14. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    Does [DeallocateOnJobCompletion] work on other collections now other than NativeArray? When can Dispose(JobHandle) be called? After scheduling a job?
     
  15. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    Nope

    Think of it as a job that disposes the collection. This works for all collection types.

    Yes it works after scheduling a job as long as you have your dependencies ordered correctly.