Introduction to NativeContainer
Understand Unity's custom thread-safe type, NativeContainer.
읽는 시간 4분최근 업데이트: 12일 전
NativeContainerNativeContainerTypes of NativeContainers
The namespace contains the following built-in objects:
Unity.CollectionsNativeContainer- : An unmanaged array which exposes a buffer of native memory to managed code
NativeArray - : Gets a subset of a
NativeSlicefrom a particular position to a certain length.NativeArray
Read and write access
By default, when a job has access to a instance, it has both read and write access. This configuration can slow performance. This is because the job system doesn’t allow you to schedule a job that has write access to a instance at the same time as another job that’s writing to it.
NativeContainerNativeContainerHowever, If a job doesn’t need to write to a instance, you can mark the with the attribute, like so:
NativeContainerNativeContainer[ReadOnly][ReadOnly]public NativeArray<int> input;
In the above example, you can execute the job at the same time as other jobs that also have read-only access to the first .
NativeArrayMemory allocators
When you create a instance, you must specify the memory allocation type that you need. The allocation type you use depends on how long you would like to keep the native container available for. This way you can tailor the allocation to get the best performance possible in each situation.
NativeContainerThere are three Allocator types for memory allocation and release. You must specify the appropriate one when instantiating a instance:
NativeContainerNativeContainer- : The fastest allocation. Use it for allocations with a lifespan of one frame or fewer. You can’t use
Allocator.Tempto pass allocations toTempinstances stored in a job's member field.NativeContainer - : A slower allocation than
Allocator.TempJobbut faster thanTemp. Use it for thread-safe allocations within a lifespan of four frames. Important: You mustPersistentof this allocation type within four frames, or the console prints a warning, generated from the native code. Most small jobs use this allocation type.Dispose - : The slowest allocation but can last as long as you need it to, and if necessary, throughout the application’s lifetime. It’s a wrapper for a direct call to
Allocator.Persistent. Longer jobs can use this NativeContainer allocation type. Don’t usemallocwhere performance is essential.Persistent
For example:
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
NativeContainer safety system
The safety system is built into all instances. It tracks what reads or writes to any instance, and uses that information to enforce certain rules on the use of s that makes them behave in a deterministic way across multiple jobs and threads.
NativeContainerNativeContainerNativeContainerFor example, if two independent scheduled jobs write to the same , this is unsafe because you can’t predict which job executes first. This means that you won’t know which of the jobs will overwrite data from the other. The safety system throws an exception with a clear error message that explains why and how to solve the problem, when you schedule the second job.
NativeArrayIf you want to schedule two jobs that write to the same instance, you can schedule the jobs with a dependency. The first job writes to the , and once it has finished executing, the next job safely reads and writes to that same . Introducing the dependency guarantees that the jobs always execute in a consistent order and that the resulting data in the is deterministic.
NativeContainerNativeContainerNativeContainerNativeContainerThe safety system allows multiple jobs to read from the same data in parallel.
These read and write restrictions also apply when accessing data from the main thread. For example, if you try to read the contents of a NativeContainer before the job that writes to it has completed, the safety system throws an error. Likewise, if you try to write to a NativeContainer while there are still pending jobs that read or write to it, then the safety system also throws an error.
Also, because NativeContainers don’t implement , you can’t directly change the contents of a . For example, is the same as writing which doesn’t update the value in .
ref returnNativeContainernativeArray[0]++;var temp = nativeArray[0]; temp++;nativeArrayInstead, you must copy the data from the index into a local temporary copy, modify that copy, and save it back. For example:
MyStruct temp = myNativeArray[i];temp.memberVariable = 0;myNativeArray[i] = temp;