### Custom Allocator Example Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-define.md This example demonstrates how to create a custom allocator, register it with AllocatorManager, and initialize allocated memory. It also shows how to increment an allocation count. ```cs public unsafe struct MyCustomAllocator : IAllocator { public AllocatorManager.AllocatorHandle Handle; public int AllocationCount; public byte InitialValue; public MyCustomAllocator(byte initialValue) { Handle = AllocatorManager.AllocatorHandle.Invalid; AllocationCount = 0; InitialValue = initialValue; } public static void* AllocatorFunction(AllocatorManager.AllocatorHandle handle, int size, int alignment) { var allocator = AllocatorManager.GetAllocator(handle); allocator.AllocationCount++; var ptr = Memory.Unmanaged.Allocate(size, alignment); Memory.Set(ptr, allocator.InitialValue, size); return ptr; } public void Initialize(AllocatorManager.AllocatorHandle handle) { Handle = handle; AllocatorManager.RegisterFunction(handle, AllocatorFunction); } public void Dispose() { // No resources to free for this allocator } } public class AllocatorCustomTests { [Test] public void CustomAllocator_Allocate_InitializesMemoryAndIncrementsCount()] { var allocator = new MyCustomAllocator(0xAA); AllocatorManager.RegisterAllocator(ref allocator); var handle = allocator.Handle; var size = 128; var alignment = 16; var ptr = AllocatorManager.Allocate(handle, size, alignment); Assert.AreNotEqual(IntPtr.Zero, (IntPtr)ptr); Assert.AreEqual(1, allocator.AllocationCount); // Verify memory initialization for (int i = 0; i < size; ++i) { Assert.AreEqual(0xAA, ((byte*)ptr)[i]); } AllocatorManager.Free(handle, ptr); AllocatorManager.UnregisterAllocator(handle); } } ``` -------------------------------- ### Full example of a custom allocator in a user structure Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-use.md This example demonstrates the complete implementation of a custom allocator within a user structure, including creation, usage with NativeArray, and disposal. ```csharp // Example custom allocator public struct ExampleCustomAllocator : IDisposable { public AllocatorHandle Handle; public ExampleCustomAllocator(AllocatorManager.AllocatorHandle handle) { Handle = handle; } public void Initialize(byte initialValue) { // Initialize memory with a specific value unsafe { byte* memory = (byte*)Handle.Reallocate(0, 1, 1); *memory = initialValue; } } public void Dispose() { // Rewind the allocator handle to invalidate child allocators and safety handles Handle.Rewind(); // Unregister the allocator AllocatorManager.RemoveAllocator(Handle); // Dispose the memory used to store the allocator Handle.Dispose(); } } // Example user structure that contains the custom allocator internal struct ExampleCustomAllocatorStruct : IDisposable { // Use AllocatorHelper to help creating the example custom alloctor AllocatorHelper customAllocatorHelper; // Custom allocator property for accessibility public ref ExampleCustomAllocator customAllocator => ref customAllocatorHelper.Allocator; // Create the example custom allocator void CreateCustomAllocator(AllocatorManager.AllocatorHandle backgroundAllocator, byte initialValue) { // Allocate the custom allocator from backgroundAllocator and register the allocator customAllocatorHelper = new AllocatorHelper(backgroundAllocator); // Set the initial value to initialize the memory customAllocator.Initialize(initialValue); } public void UseCustomAllocator() { // Use CollectionHelper to create a NativeArray with the custom allocator var nativeArray = CollectionHelper.CreateNativeArray(10, customAllocator, NativeArrayOptions.UninitializedMemory); // Use the native array... // Dispose the native array and the custom allocator CollectionHelper.Dispose(nativeArray); } public void UseCustomAllocatorUnsafe() { // Allocate memory using AllocatorManager.Allocate var ptr = AllocatorManager.Allocate(customAllocator, 10 * sizeof(int)); // Use the allocated memory... // Free the memory using AllocatorManager.Free AllocatorManager.Free(customAllocator, ptr); } public void DisposeCustomAllocator() { // Rewind the allocator handle to invalidate child allocators and safety handles customAllocator.Rewind(); // Unregister the allocator (this is handled by AllocatorHelper's Dispose) // Dispose the memory used to store the allocator (this is handled by AllocatorHelper's Dispose) customAllocatorHelper.Dispose(); } public void Dispose() { DisposeCustomAllocator(); } } ``` -------------------------------- ### Utility Class for List Setup and Teardown Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md Provides common setup and teardown logic for NativeList and System.Collections.Generic.List. Use this to reduce boilerplate code in performance tests. ```csharp static class ListUtil { static public void SetupTeardown(ref NativeList container, int capacity, bool addValues) { if (capacity >= 0) { container = new NativeList(capacity, Allocator.Persistent); if (addValues) { for (int i = 0; i < capacity; i++) container.Add(i); } } else container.Dispose(); } static public object SetupTeardownBCL(int capacity, bool addValues) { if (capacity < 0) return null; var list = new System.Collections.Generic.List(capacity); if (addValues) { for (int i = 0; i < capacity; i++) list.Add(i); } return list; } } ``` -------------------------------- ### Full Example of a Rewindable Allocator Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-rewindable.md This comprehensive example illustrates the complete lifecycle and usage of a rewindable allocator, including its creation, allocation, manipulation, and eventual disposal. It serves as a reference for implementing rewindable allocator patterns. ```csharp public class AllocatorRewindableTests { [Test] public void RewindableAllocatorExample() { var allocator = new RewindableAllocator(Allocator.Temp); var buffer = allocator.Allocate(10); for (int i = 0; i < 10; i++) { buffer[i] = i; } allocator.Rewind(); var buffer2 = allocator.Allocate(5); for (int i = 0; i < 5; i++) { buffer2[i] = i * 2; } allocator.DisposeRewindableAllocator(); } } ``` -------------------------------- ### Allocator Function Example Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-define.md This example shows a typical AllocatorFunction for a custom allocator. It handles allocation, deallocation, and reallocation requests based on the provided block information. ```csharp static void AllocatorFunction(ref Block block) { // This is a placeholder for the actual allocator logic. // In a real implementation, this function would contain the core // logic for allocating, deallocating, and reallocating memory. // It would typically interact with the underlying memory management system. // Example: If the block requires allocation, allocate memory. if (block.RequiresAllocs) { // Allocate memory using the underlying allocator (e.g., Allocator.Persistant) // block.Data = AllocatorManager.Allocate(Allocator.Persistant, block.Count, block.Stride); } // Example: If the block needs to be deallocated, deallocate memory. if (block.IsDeallocate) { // Deallocate memory if it was previously allocated // AllocatorManager.Free(Allocator.Persistant, block.Data); } // Example: Handle reallocation if necessary // if (block.IsReallocate) // { // block.Data = AllocatorManager.Reallocate(Allocator.Persistant, block.Data, block.Count, block.Stride, block.PreviousData.SizeT); // } } ``` -------------------------------- ### NativeList.ParallelWriter Job Example Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/parallel-readers.md This example demonstrates a job that writes integers to a `NativeList` using its `ParallelWriter`. The job is scheduled to run in parallel. ```csharp struct ParallelWriterJob : IJobParallelFor { public NativeList.ParallelWriter List; public void Execute(int i) { List.Add(i); } } ``` -------------------------------- ### Allocator Aliasing Example Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-aliasing.md Demonstrates how to create an alias for an existing collection's allocation. Aliases do not allocate their own memory and do not need to be disposed. ```csharp NativeList original = new NativeList(Allocator.Temp); original.Add(1); // Alias the entire allocation of original UnsafeList alias = new UnsafeList(original.Allocator, original.Length, original.Ptr); alias.Add(2); // original now contains 1 and 2 Debug.Log(original.IsCreated); // Disposing the alias does nothing alias.Dispose(); // Disposing the original invalidates the alias original.Dispose(); // Accessing the alias after original is disposed is unsafe // Debug.Log(alias.IsCreated); // This would throw an exception ``` -------------------------------- ### Implement IAllocator Interface Properties Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-define.md This example shows how to set up the required properties for the IAllocator interface, excluding the Try and AllocatorFunction methods. Ensure all necessary properties like Handle, ToAllocator, IsCustomAllocator, and IsAutoDispose are implemented. ```csharp // A custom allocator must implement AllocatorManager.IAllocator interface [BurstCompile(CompileSynchronously = true)] internal struct ExampleCustomAllocator : AllocatorManager.IAllocator { // A custom allocator must contain AllocatorManager.AllocatorHandle AllocatorManager.AllocatorHandle m_handle; // Implement the Function property required by IAllocator interface public AllocatorManager.TryFunction Function => AllocatorFunction; // Implement the Handle property required by IAllocator interface public AllocatorManager.AllocatorHandle Handle { get { return m_handle; } set { m_handle = value; } } // Implement the ToAllocator property required by IAllocator interface public Allocator ToAllocator { get { return m_handle.ToAllocator; } } // Implement the IsCustomAllocator property required by IAllocator interface public bool IsCustomAllocator { get { return m_handle.IsCustomAllocator; } } // Implement the IsAutoDispose property required by IAllocator interface // Allocations made by this example allocator are not automatically disposed. // This implementation can be skipped because the default implementation of // this property is false. public bool IsAutoDispose { get { return false; } } // Implement the Dispose method required by IDisposable interface because // AllocatorManager.IAllocator implements IDisposable public void Dispose() { // Make sure no memory leaks Assert.AreEqual(0, m_allocationCount); m_handle.Dispose(); } } ``` -------------------------------- ### Implement IBenchmarkAllocator for RewindableAllocator Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/README.md This struct implements the `IBenchmarkAllocator` interface to simplify setup, teardown, and `Rewind` functionality for `RewindableAllocator` on a per-test-run basis. ```csharp struct Rewindable_FixedSize : IBenchmarkAllocator { RewindableAllocationInfo allocInfo; public void CreateAllocator(Allocator builtinOverride) => allocInfo.CreateAllocator(builtinOverride); public void DestroyAllocator() => allocInfo.DestroyAllocator(); public void Setup(int workers, int size, int allocations) => allocInfo.Setup(workers, size, 0, allocations); public void Teardown() => allocInfo.Teardown(); public void Measure(int workerI) => allocInfo.Allocate(workerI); } ``` -------------------------------- ### Try Method for Allocate/Deallocate Memory Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-define.md The Try method handles memory allocation and deallocation. This example demonstrates allocating memory from Allocator.Persistant, initializing it, and managing an allocation count. It also decrements the count during deallocation. ```csharp public bool Try(ref Block block) { // Allocate memory from Allocator.Persistant if (block.RequiresAllocs) { block.Data = AllocatorManager.Allocate(Allocator.Persistant, block.Count, block.Stride); m_allocationCount++; } // Initialize allocated memory with a user-configured value if (block.IsDefaultInitialize) { UnsafeUtility.MemClear(block.Data, block.Count * block.Stride); // Initialize with a user-configured value // For example, initialize with a specific pattern or value // For simplicity, we'll just ensure it's cleared here. } // Decrement allocation count when deallocating if (block.IsDeallocate) { m_allocationCount--; } // Return true to indicate success return true; } ``` -------------------------------- ### Define Benchmark Interface Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md An interface specifies test setup, teardown, and measurement logic for each type being measured. This allows for a unified interface for both native and managed code paths. ```csharp public interface IMyExampleBenchmark { public void SetupTeardown(int capacity); public object SetupTeardownBCL(int capacity); public void Measure(); public void MeasureBCL(object container); } ``` -------------------------------- ### Declare and create a custom allocator Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-use.md Use AllocatorHelper to simplify the creation and registration of a custom allocator within a struct. Ensure the allocator is initialized with a starting value. ```csharp // Example user structure that contains the custom allocator internal struct ExampleCustomAllocatorStruct { // Use AllocatorHelper to help creating the example custom alloctor AllocatorHelper customAllocatorHelper; // Custom allocator property for accessibility public ref ExampleCustomAllocator customAllocator => ref customAllocatorHelper.Allocator; // Create the example custom allocator void CreateCustomAllocator(AllocatorManager.AllocatorHandle backgroundAllocator, byte initialValue) { // Allocate the custom allocator from backgroundAllocator and register the allocator customAllocatorHelper = new AllocatorHelper(backgroundAllocator); // Set the initial value to initialize the memory customAllocator.Initialize(initialValue); } } ``` -------------------------------- ### Benchmark Container for List Add Operations Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/README.md Defines a benchmark container to measure the performance of adding elements to NativeList, UnsafeList, and System.Collections.Generic.List. It includes methods for parameter setup and allocation of different container types. ```csharp struct ListAdd : IBenchmarkContainer { int capacity; NativeList nativeContainer; UnsafeList unsafeContainer; void IBenchmarkContainer.SetParams(int capacity, params int[] args) => this.capacity = capacity; public void AllocNativeContainer(int capacity) => ListUtil.AllocInt(ref nativeContainer, capacity, false); public void AllocUnsafeContainer(int capacity) => ListUtil.AllocInt(ref unsafeContainer, capacity, false); public object AllocBclContainer(int capacity) => ListUtil.AllocBclContainer(capacity, false); public void MeasureNativeContainer() { for (int i = 0; i < capacity; i++) nativeContainer.Add(i); } public void MeasureUnsafeContainer() { for (int i = 0; i < capacity; i++) unsafeContainer.Add(i); } public void MeasureBclContainer(object container) { var bclContainer = (System.Collections.Generic.List)container; for (int i = 0; i < capacity; i++) bclContainer.Add(i); } } ``` -------------------------------- ### Array Reinterpretation Example Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-aliasing.md Shows how to reinterpret an array's data as a different element type without copying. This is useful when the underlying byte representation can be interpreted differently, such as int (4 bytes) vs. ushort (2 bytes). ```csharp NativeArray ushortArray = new NativeArray(4, Allocator.Temp); // Reinterpret the ushort array as an int array NativeArray intArray = ushortArray.Reinterpret(2); // The length of the reinterpreted array is halved because each int is 4 bytes (2 ushorts) Debug.Log(intArray.Length); // Dispose the original array; the reinterpreted array is invalidated ushortArray.Dispose(); ``` -------------------------------- ### Benchmark Runner Class Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md A generic runner class that brings together the glue pieces. It ensures the correct code path is executed and measured by the performance framework, handling setup, teardown, and measurement calls. ```csharp [BurstCompile(CompileSynchronously = true)] public static class MyExampleRunner where T : unmanaged, IMyExampleBenchmark { ``` -------------------------------- ### Configure and Run Benchmarks Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md A configuration class can store common data and provide an interface for running benchmarks. The `GenerateMarkdown` method initiates benchmark tests and generates a markdown report. ```csharp public static class MyExampleConfig { public const int BCL = -1; internal const int kCountWarmup = 5; internal const int kCountMeasure = 10; #if UNITY_EDITOR [UnityEditor.MenuItem("Benchmark Example/Generate My Benchmarks")] #endif static void RunBenchmarks() => BenchmarkGenerator.GenerateMarkdown( "Containers Example", typeof(MyExampleType), "Temp/performance-comparison-example.md", $"Example benchmark - {kCountMeasure} runs after {kCountWarmup} warmup runs", "Legend", new string[] { "`(B)` = Burst Compiled", "`(BCL)` = Base Class Library implementation (such as provided by Mono or .NET)", }); } ``` -------------------------------- ### Benchmark List Foreach Operation Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md Benchmarks the `foreach` iteration performance on a `List` with a variable number of elements. Uses `MyExampleRunner` to execute the benchmark. ```csharp [Test, Performance] [Category("Performance")] public unsafe void Foreach( [Values(10000, 100000, 1000000)] int insertions, [Values] MyExampleType type) { MyExampleRunner.Run(insertions, type); } ``` -------------------------------- ### Declare and Create a Rewindable Allocator Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-rewindable.md Use the AllocatorHelper wrapper to declare and initialize a rewindable allocator. This involves allocating the allocator itself, registering it, and pre-allocating its first memory block. ```csharp // Example user structure internal struct ExampleStruct { // Use AllocatorHelper to help creating a rewindable alloctor AllocatorHelper rwdAllocatorHelper; // Rewindable allocator property for accessibility public ref RewindableAllocator RwdAllocator => ref rwdAllocatorHelper.Allocator; // Create the rewindable allocator void CreateRewindableAllocator(AllocatorManager.AllocatorHandle backgroundAllocator, int initialBlockSize, bool enableBlockFree = false) { // Allocate the rewindable allocator from backgroundAllocator and register the allocator rwdAllocatorHelper = new AllocatorHelper(backgroundAllocator); // Allocate the first memory block with initialBlockSize in bytes, and indicate whether // to enable the rewindable allocator with individual block free through enableBlockFree RwdAllocator.Initialize(initialBlockSize, enableBlockFree); } } ``` -------------------------------- ### Allocator.Temp Safety Handle Issue Example Source: https://github.com/needle-mirror/com.unity.collections/blob/master/README.md Demonstrates a known issue where Allocator.Temp allocations share a secondary safety handle, leading to InvalidOperationException when one collection invalidates the handle used by another. ```csharp var list = new NativeList(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 NativeParallelHashSet(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]; ``` -------------------------------- ### Benchmark List IsEmpty Operation Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md Benchmarks the `IsEmpty` operation for a `List` with varying initial capacities. Uses `MyExampleRunner` to execute the benchmark. ```csharp [Benchmark(typeof(MyExampleType))] [BenchmarkNameOverride("List")] class MyListMeasurements { [Test, Performance] [Category("Performance")] public unsafe void IsEmpty_x_100k( [Values(0, 100)] int capacity, [Values] MyExampleType type) { MyExampleRunner.Run(capacity, type); } ``` -------------------------------- ### Benchmark List Add Operation Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md Benchmarks the `Add` operation for a `List`, measuring performance as the list grows to a specified size. Includes a footnote indicating incremental growth. ```csharp [Test, Performance] [Category("Performance")] [BenchmarkTestFootnote("Incrementally reaching size of `growTo`")] public unsafe void AddGrow( [Values(65536, 1024 * 1024)] int growTo, [Values] MyExampleType type) { MyExampleRunner.Run(growTo, type); } ``` -------------------------------- ### Benchmark Execution Logic Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md This code defines the execution logic for different benchmark types (BCL, Managed, Burst Compiled) within the Unity Collections performance testing framework. It utilizes the BenchmarkMeasure class to run and measure performance, handling setup and teardown for each type. ```csharp [BurstCompile(CompileSynchronously = true)] unsafe struct BurstCompiledJob : IJob { [NativeDisableUnsafePtrRestriction] public T* methods; public void Execute() => methods->Measure(); } public static unsafe void Run(int capacity, MyExampleType type) { var methods = new T(); switch (type) { case (MyExampleType)(MyExampleConfig.BCL): object container = null; BenchmarkMeasure.Measure( typeof(T), MyExampleConfig.kCountWarmup, MyExampleConfig.kCountMeasure, () => methods.MeasureBCL(container), () => container = methods.SetupTeardownBCL(capacity), () => container = methods.SetupTeardownBCL(-1)); break; case MyExampleType.Managed: BenchmarkMeasure.Measure( typeof(T), MyExampleConfig.kCountWarmup, MyExampleConfig.kCountMeasure, () => methods.Measure(), () => methods.SetupTeardown(capacity), () => methods.SetupTeardown(-1)); break; case MyExampleType.BurstCompiled: BenchmarkMeasure.Measure( typeof(T), MyExampleConfig.kCountWarmup, MyExampleConfig.kCountMeasure, () => new BurstCompiledJob { methods = (T*)UnsafeUtility.AddressOf(ref methods) }.Run(), () => methods.SetupTeardown(capacity), () => methods.SetupTeardown(-1)); break; } } } ``` ``` -------------------------------- ### Benchmark for Growing a NativeList Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md Implements IMyExampleBenchmark to measure the performance of adding elements to a NativeList. The Measure method contains the core logic to be benchmarked. ```csharp struct ListAddGrow : IMyExampleBenchmark { int toAdd; NativeList nativeContainer; public void SetupTeardown(int capacity) { toAdd = capacity; ListUtil.SetupTeardown(ref nativeContainer, 0, false); } public object SetupTeardownBCL(int capacity) { toAdd = capacity; return ListUtil.SetupTeardownBCL(0, false); } public void Measure() { for (int i = 0; i < toAdd; i++) nativeContainer.Add(i); } public void MeasureBCL(object container) { var list = (System.Collections.Generic.List)container; for (int i = 0; i < toAdd; i++) list.Add(i); } } ``` -------------------------------- ### Benchmark for Iterating a NativeList with Foreach Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.PerformanceTests/Unity.PerformanceTesting.Benchmark/README.md Tests the performance of iterating over a NativeList using a foreach loop. Uses Volatile.Write to prevent the loop from being optimized away. ```csharp struct ListForEach : IMyExampleBenchmark { NativeList nativeContainer; public void SetupTeardown(int capacity) => ListUtil.SetupTeardown(ref nativeContainer, capacity, true); public object SetupTeardownBCL(int capacity) => ListUtil.SetupTeardownBCL(capacity, true); public void Measure() { int value = 0; foreach (var element in nativeContainer) Volatile.Write(ref value, element); } public void MeasureBCL(object container) { int value = 0; var list = (System.Collections.Generic.List)container; foreach (var element in list) Volatile.Write(ref value, element); } } ``` -------------------------------- ### Use a custom allocator to allocate memory for Native containers Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-use.md When using custom allocators with Native containers like NativeArray, utilize CollectionHelper.CreateNativeArray for allocation and CollectionHelper.Dispose for deallocation. This ensures proper safety handle management. ```csharp public void UseCustomAllocator() { // Create a custom allocator instance var customAllocator = new ExampleCustomAllocator(Allocator.Temp); // Use CollectionHelper to create a NativeArray with the custom allocator var nativeArray = CollectionHelper.CreateNativeArray(10, customAllocator, NativeArrayOptions.UninitializedMemory); // Use the native array... // Dispose the native array and the custom allocator CollectionHelper.Dispose(nativeArray); customAllocator.Dispose(); } ``` -------------------------------- ### Use a custom allocator to allocate memory for Unsafe containers Source: https://github.com/needle-mirror/com.unity.collections/blob/master/Documentation~/allocator-custom-use.md For Unsafe containers, allocate memory directly using AllocatorManager.Allocate with your custom allocator and free it with AllocatorManager.Free. This bypasses the safety handle system. ```csharp public void UseCustomAllocatorUnsafe() { // Create a custom allocator instance var customAllocator = new ExampleCustomAllocator(Allocator.Temp); // Allocate memory using AllocatorManager.Allocate var ptr = AllocatorManager.Allocate(customAllocator, 10 * sizeof(int)); // Use the allocated memory... // Free the memory using AllocatorManager.Free AllocatorManager.Free(customAllocator, ptr); customAllocator.Dispose(); } ```