Allocator overview
An allocator governs unmanaged memory from which you can make allocations. Different allocators organize and track their memory in different ways. The Collections package includes the following allocators:
Allocator.Temp: The fastest allocator, for short-lived allocations. You can't pass this allocator to a job.Allocator.TempJob: A short-lived allocator that you can pass into jobs.Allocator.Persistent: The slowest allocator for indefinite lifetime allocations. You can pass this allocator to a job.
Allocator.Temp
Each frame, the main thread creates a Temp allocator which it deallocates in its entirety at the end of the frame. Each job also creates one Temp allocator per thread, and deallocates them in their entirety at the end of the job. Because a Temp allocator gets discarded as a whole, you don't need to manually deallocate Temp allocations, and doing so does nothing. The minimum alignment of Temp allocations is 64 bytes.
Temp allocations are only safe to use in the thread and the scope where they were allocated. While you can make Temp allocations within a job, you can't pass main thread Temp allocations into a job. For example, you can't pass a native array that's Temp allocated in the main thread into a job.
Allocator.TempJob
You must deallocate TempJob allocations within 4 frames of their creation. The 4-frame limit provides some margin for allocations that need to persist across a few frames. The minimum alignment of TempJob allocations is 16 bytes.
If a TempJob allocation isn't disposed within 4 frames, Unity writes a warning message but the allocation remains valid. Unity doesn't automatically deallocate such allocation, and you must still explicitly dispose it in your code to free the memory.
Exceeding the 4-frame limit has the following consequences:
- Performance degradation: The
TempJoballocator has a fixed memory pool. If long-lived allocations accumulate and exhaust this pool, subsequent allocations fall back toAllocator.Persistent, which is significantly slower. - Memory leak reports: If allocations still exist when the
TempJoballocator is disposed (for example, when the application exits), Unity reports them as memory leaks when native leak detection is enabled.
Note
For Native- collection types, safety checks log warnings when a TempJob allocation exceeds 4 frames. For Unsafe- collection types, Unity doesn't perform safety checks, and doesn't log warnings even if an allocation exceeds 4 frames.
If your job or allocation might regularly exceed 4 frames, use Allocator.Persistent instead.
If you need an intermediate-lifetime allocator optimized for durations between TempJob and Persistent, consider using a custom allocator or a rewindable allocator.
Allocator.Persistent
Because Persistent allocations can remain indefinitely, safety checks can't detect if a Persistent allocation has outlived its intended lifetime. As such, you must deallocate a Persistent allocation when you no longer need it. The minimum alignment of Persistent allocations is 16 bytes.
Deallocating an allocator
Each collection retains a reference to the allocator that allocated its memory. This is because you must specify the allocator to deallocate its memory.
- An
Unsafe-collection'sDisposemethod deallocates its memory. - A
Native-collection'sDisposemethod deallocates its memory and frees the handles needed for safety checks. - An enumerator's
Disposemethod does nothing. The method exists only to fulfill theIEnumerator<T>interface.
To dispose a collection after the jobs which need it have run, you can use the Dispose(JobHandle) method. This creates and schedules a job which disposes of the collection, and this new job takes the input handle as its dependency. Effectively, the method defers disposal until after the dependency runs:
NativeArray<int> nums = new NativeArray<int>(10, Allocator.TempJob);
// Create and schedule a job that uses the array.
ExampleJob job = new ExampleJob { Nums = nums };
JobHandle handle = job.Schedule();
// Create and schedule a job that will dispose the array after the ExampleJob has run.
// Returns the handle of the new job.
handle = nums.Dispose(handle);
IsCreated property
The IsCreated property of a collection is false only in the following cases:
- Immediately after creating a collection with its default constructor.
- After
Disposehas been called on the collection.
Note
You don't need to use a collection's default constructor. The constructor is only available because C# requires all structs have a public default constructor.
Calling Dispose on a collection sets IsCreated to false only for that struct, and not in any copies of the struct. IsCreated might still be true even after the collection's underlying memory is deallocated in the following situations:
Disposewas called on a different copy of the struct.- The underlying memory was deallocated via an alias.