# Introduction to allocators

> Understand how to use an allocator to manage unmanaged memory.

An allocator controls the allocation of unmanaged memory. Different allocators organize and track their memory in different ways. The `Unity.Collections` APIs include the following allocators:

* [`Allocator.Temp`](#allocatortemp): The fastest allocator, for short-lived allocations. You can't pass this allocator to a job.
* [`Allocator.TempJob`](#allocatortempjob): A short-lived allocator that you can pass into jobs.
* [`Allocator.Persistent`](#allocatorpersistent): The slowest allocator for indefinite lifetime allocations. You can pass this allocator to a job.
* [Rewindable allocator](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-rewindable.md): A custom allocator that's fast and thread safe, and can rewind and free all your allocations at one point.

To use these types, pass an [`Allocator`](/engine/7000.0/script-reference/unity/collections/allocator.md) enum value to select the native allocator type's memory label to use. Alternatively, for low-level allocations where you need custom categorization, you can create and pass a [`MemoryLabel`](/engine/7000.0/script-reference/unity/collections/memorylabel.md) instance directly to allocation functions. If a chosen `Temp` allocator is full, Unity chooses a fallback allocator instead (usually `TempJob`, or `Temp` overflow).

The [Entities package](https://docs.unity3d.com/Packages/com.unity.entities@latest) has its own set of custom prebuilt allocators. For more information, refer to [Memory allocators](https://docs.unity3d.com/Packages/com.unity.entities@latest/index.html?subfolder=/manual/memory-allocators.html).

## Allocator feature comparison

The following table compares the features of the different built-in allocators:

| **Allocator type**                                                                                  | **Lifetime**                | **Automatically freed allocations** | **Can pass to jobs** | **Min Allocation Alignment (bytes)** |
| --------------------------------------------------------------------------------------------------- | --------------------------- | ----------------------------------- | -------------------- | ------------------------------------ |
| [`Allocator.Temp`](/engine/7000.0/script-reference/unity/collections/allocator/temp.md)             | A frame or a job            | Yes                                 | No                   | 64                                   |
| [`Allocator.TempJob`](/engine/7000.0/script-reference/unity/collections/allocator/tempjob.md)       | Within 4 frames of creation | No                                  | Yes                  | 16                                   |
| [`Allocator.Persistent`](/engine/7000.0/script-reference/unity/collections/allocator/persistent.md) | Indefinite                  | No                                  | Yes                  | 16                                   |

Alternatively, you can create a custom rewindable allocator, which can be passed to jobs, has an indefinite allocation lifetime, and a 64 byte minimum allocation alignment. For more information, refer to [Rewindable allocator](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-rewindable.md).

### Memory label mapping ##memory-label-mapping

The allocators map to memory labels and [Memory Profiler](https://docs.unity3d.com/Packages/com.unity.memoryprofiler@latest) regions as follows:

* `Allocator.Temp` maps to the label`TempAlloc` and a Thread-local Temporary Allocator. Depending on the allocating thread, this might show in the Memory Profiler under the allocator region `ALLOC_TEMP_TLS` as `ALLOC_TEMP_MAIN`, `ALLOC_TEMP_THREAD`, `ALLOC_TEMP_<ThreadName>` or under `Native > Unity Subsystems > UnsafeUtility > Malloc(Temp) PoolUnsafeUtility` with allocations under the label `Utility`.
* `Allocator.TempJob` maps to `TempJobAlloc` and is reported in the Memory Profiler under the allocator region `ALLOC_TEMP_JOB_4_FRAMES` potentially with the post-fix `(JobTemp)`.
* `Allocator.Persistent` maps to `Default`/`Malloc` and might show under the allocator region or `ALLOC_DEFAULT` and either `ALLOC_DEFAULT_MAIN` or `ALLOC_DEFAULT_THREAD` (or depending on the size of the allocation, `ALLOC_BUCKET`) under `Native >Unity Subsystems >UnsafeUtility >Malloc(Persistent) UnsafeUtility`.

## Temp allocator ##allocatortemp

`Temp` is Unity's temporary allocator type. It's designed for small, short-lived allocations that can't cross a frame boundary, such as temporary allocations made within a single job. The `Temp` type is a stack type allocator for small amounts of memory that Unity allocates from the main memory pool.

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 has no effect.

`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.

There are multiple `Temp` allocators, and each thread that needs an allocator has one. Unity recycles `Temp` allocators each frame ensuring a clean memory usage pattern. However, if memory spills over into the fallback allocators, their memory might get fragmented.

You can use [`Profiler.GetTempAllocatorSize`](/engine/7000.0/script-reference/unityengine/profiling/profiler/gettempallocatorsize.md) and [`Profiler.SetTempAllocatorRequestedSize`](/engine/7000.0/script-reference/unityengine/profiling/profiler/settempallocatorrequestedsize.md) to get and set the size for `Temp` allocators. The minimum alignment of `Temp` allocations is 64 bytes.

The sizes for the `Temp` allocator default to:

* Editor: 16 MB main thread, 256 KB worker threads.
* Players: 4 MB main thread, 256 KB worker threads.

If these sizes are exceeded, allocations on the main thread fall back to the `TempJob` allocator, and on other threads they fall back to a `Temp` overflow allocator. For more information on temporary native allocations, refer to [Thread storage local (TLS) allocator](/engine/7000.0/manual/analysis/performance-memory/native-memory/allocators.md#tls).

### Shared AtomicSafetyHandle for Temp allocations

All containers allocated with `Allocator.Temp` on the same thread use a shared `AtomicSafetyHandle` instance rather than each having their own. Most of the time, this isn't an issue because you can't pass `Temp` allocated collections into a job.

However, when you use `NativeHashMap`, `NativeParallelMultiHashMap`, `NativeHashSet`, and `NativeList` together with their secondary safety handle, this shared `AtomicSafetyHandle` instance is a problem.

A secondary safety handle ensures a `NativeArray` that aliases a `NativeList` is invalidated when the `NativeList` is reallocated due to resizing.

Operations that invalidate an enumerator for these collection types, or that invalidate the `NativeArray` that `NativeList.AsArray` returns, also invalidate all other previously acquired enumerators. For example, the following throws an error when safety checks are enabled:

```c#
var list = new NativeList<int>(Allocator.Temp);
list.Add(1);

// This array uses the secondary safety handle of the list, which is
// shared between all Allocator.Temp allocations.
var array = list.AsArray();

var list2 = new NativeHashSet<int>(Allocator.Temp);

// This invalidates the secondary safety handle, which is also used
// by the list above.
list2.TryAdd(1);

// This throws an InvalidOperationException because the shared safety
// handle was invalidated.
var x = array[0];
```

## TempJob allocator ##allocatortempjob

This type uses a linear style allocator which Unity stores in a `TempJob` area that it allocates from main memory. It's designed for larger temporary allocations that are passed from job to job, and those that might carry data between frames. If the allocations aren't disposed of within 4 frames of their creation, a warning is displayed in the Unity Editor.

> **Note:**
>
> If the memory available is exhausted, Unity makes the overspill allocations in main memory (malloc). Most platforms can have up to 64 MB of `TempJob` memory, but on smaller memory systems this limit can be as low as 16 MB.

If this allocator is full, allocations fall back to a `TempJob` overflow allocator. For more information on temporary job allocations, refer to [Thread safe linear allocator](/engine/7000.0/manual/analysis/performance-memory/native-memory/allocators.md#thread-safe-linear).

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 `TempJob` allocator has a fixed memory pool. If long-lived allocations accumulate and exhaust this pool, subsequent allocations fall back to `Allocator.Persistent`, which is significantly slower.
* **Memory leak reports**: If allocations still exist when the `TempJob` allocator is disposed (for example, when the application exits), Unity reports them as memory leaks when [native leak detection](/engine/7000.0/script-reference/unity/collections/nativeleakdetection.md) is enabled.

For `Native` collection types, safety-handle checks (via `AtomicSafetyHandle`) validate correct usage and disposal. `Unsafe` collection types don't have these safety handles, so they don't perform those usage/disposal validation checks.

A separate warning mechanism for when a `TempJob` allocation exceeds 4 frames is driven by allocation tracking rather than safety handles. It applies whenever leak detection is enabled. Because `Unsafe` collections still allocate through tracked paths (for example, `UnsafeList` uses [`UnsafeUtility.MallocTracked`](/engine/7000.0/script-reference/unity/collections/lowlevel/unsafe/unsafeutility/malloctracked.md)), overdue `TempJob` allocations from `Unsafe` collections can still trigger this warning independently of the safety-handle checks. For more information, refer to [`NativeLeakDetection`](/engine/7000.0/script-reference/unity/collections/nativeleakdetection.md).

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](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-custom-define.md) or a [rewindable allocator](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-rewindable.md).

## Persistent allocator ##allocatorpersistent

This allocator allocates memory with no time restrictions, is only limited by the amount of free memory on a device, and therefore has no fallback. It can exist for as long as you need it, but the leak detection system only warns you if you don't free the allocated memory and if your handle to the memory was garbage collected. As such, you must deallocate a `Persistent` allocation when you no longer need it. Allocating persistent memory is slower than allocating temporary memory. The minimum alignment of `Persistent` allocations is 16 bytes.

## Deallocating memory

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's `Dispose` method deallocates its memory.
* A `Native-` collection's `Dispose` method deallocates its memory and frees the handles needed for safety checks.
* An enumerator's `Dispose` method does nothing. The method exists only to fulfill the `IEnumerator<T>` interface.

To dispose a collection after the jobs that need it have run, you can use the `Dispose(JobHandle)` method. This creates and schedules a job that 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:

```cs
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 `Dispose` has been called on the collection.

> **Important:**
>
> Don't use a collection's default constructor. The constructor is only available because C# requires that 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:

* `Dispose` was called on a different copy of the struct.
* The underlying memory was deallocated via an [alias](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-aliasing.md).

## Additional resources

* [Aliasing allocators](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-aliasing.md)
* [Rewindable allocators](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-rewindable.md)
* [Define a custom allocator](/engine/7000.0/manual/analysis/performance-memory/collections/allocation/allocator-custom-define.md)
