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:
- At the beginning of OnUpdate, Complete() the job and deallocate for the next execution.
- 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
I’m leaning towards option 2. I have actually created a generic job purely to deallocate NativeArrays after I’m done using them.
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…
[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.
1 Like
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…
if you use JobComponentSystem, you don’t need to complete() by yourself.
Like Spy-Shifty said if u have to deallocate collections u should call Complete() on job that use your collection.
On JobComponentSystem you return the handle, and its complete on the end of the frame:
An exemple from my code:
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var nodesChunks = this.nodesQuery.CreateArchetypeChunkArray(Allocator.TempJob);
var returnHandle = inputDependencies;
if (nodesChunks.Length > 0)
{
var entityType = GetArchetypeChunkEntityType();
var nodeType = GetArchetypeChunkComponentType<Node>(true);
var nodeParentType = GetArchetypeChunkComponentType<NodeParent>();
this.resetedNodes.Clear(); // <- persistent NativeList
var filterJob = new FilterNodes()
{
Chunks = nodesChunks,
ResetedNodes = this.resetedNodes,
NodeType = nodeType,
NodeParentType = nodeParentType,
EntityType = entityType
};
var filterJobHandle = filterJob.Schedule(inputDependencies);
var calculateJob = new CalculateNodes()
{
ResetedNodes = this.resetedNodes.AsDeferredJobArray(),
EntityCommand = this.entityCommandBufferSystem.CreateCommandBuffer()
};
returnHandle = calculateJob.Schedule(filterJobHandle);
this.entityCommandBufferSystem.AddJobHandleForProducer(returnHandle);
}
else
{
nodesChunks.Dispose();
}
return returnHandle;
}
edit: the filter job has [DeallocateOnJobCompletion] on the chunk array.
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?
I have the same problem after fixing memory leaks, see Memory leak warnings spammed until Editor is restarted
yep, that’s the issue! So I’m not crazy then! I like not being crazy! 
I’d like to revive this thread. How is this done now? I’m still using persisting collection and clearing them before firing jobs.
[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.
1 Like
Does [DeallocateOnJobCompletion] work on other collections now other than NativeArray? When can Dispose(JobHandle) be called? After scheduling a job?
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.