NativeContainer
the safety system’s复制数据的过程的缺点是它还隔离了每个副本中作业的结果。 要克服此限制,您需要将结果存储在一种名为NativeContainer的共享内存中。
What is a NativeContainer?
NativeContainer是一种托管值类型,为本机内存提供相对安全的C#包装器。 它包含指向非托管分配的指针。 与Unity C#作业系统一起使用时,NativeContainer允许作业访问与主线程共享的数据,而不是使用副本。
有哪些类型的NativeContainer?
Unity附带一个名为NativeArray的NativeContainer。 您还可以使用NativeSlice操作NativeArray,以将NativeArray的子集从特定位置获取到特定长度。
注意:实体组件系统(ECS)包扩展Unity.Collections命名空间以包含其他类型的NativeContainer:
NativeList - 可调整大小的NativeArray。
NativeHashMap - 键和值对。
NativeMultiHashMap - 每个键有多个值。
NativeQueue - 先进先出(FIFO)队列。
NativeContainer and the safety system(安全系统)
the safety system内置于所有NativeContainer类型中。它跟踪正在读取和写入任何NativeContainer的内容。
注意:对NativeContainer类型的所有安全检查(例如越界检查,释放检查和竞争条件检查)仅在Unity编辑器和播放模式下可用。
该the safety system的一部分是DisposeSentinel和AtomicSafetyHandle。 DisposeSentinel检测到内存泄漏,如果您没有正确释放内存,则会出错。泄漏发生后很久就会发生内存泄漏错误。
使用AtomicSafetyHandle在代码中转移NativeContainer的所有权。例如,如果两个预定作业正在写入同一个NativeArray,则安全系统会抛出一个异常,并显示一条明确的错误消息,说明解决问题的原因和方法。安排违规工作时,安全系统会抛出此异常。
在这种情况下,您可以安排具有依赖关系的作业。第一个作业可以写入NativeContainer,一旦完成执行,下一个作业就可以安全地读取和写入同一个NativeContainer。从主线程访问数据时,读写限制也适用。安全系统允许多个作业并行读取相同的数据。
默认情况下,当作业可以访问NativeContainer时,它具有读写访问权限。此配置可能会降低性能。 C#作业系统不允许您安排具有对NativeContainer具有写访问权限的作业,而该作业与写入该作业的另一个作业同时进行。
如果job不需要写入NativeContainer,请使用[ReadOnly]属性标记NativeContainer,如下所示:
[ReadOnly]
public NativeArray<int> input;
在上面的示例中,您可以与其他具有对第一个NativeArray的只读访问权限的作业同时执行作业。
注意:无法防止从job中访问静态数据。 访问静态数据会绕过所有安全系统,并可能导致Unity崩溃。 有关更多信息,请参阅C# Job System提示和故障排除。
NativeContainer Allocator
创建NativeContainer时,必须指定所需的内存分配类型。分配类型取决于作业运行的时间长度。通过这种方式,您可以定制分配以在每种情况下获得最佳性能。
NativeContainer内存分配和释放有三种Allocator类型。在实例化NativeContainer时需要指定适当的一个。
Allocator.Temp分配最快。
它适用于寿命为一帧或更少的分配。您不应该使用Temp将NativeContainer分配传递给作业。您还需要在从方法调用返回之前调用Dispose方法(例如MonoBehaviour.Update,或从本机代码到托管代码的任何其他回调)。
Allocator.TempJob是比Temp更慢的分配,但比Persistent更快。
它适用于四帧生命周期内的分配,并且是线程安全的。如果不在四帧内处理它,控制台将打印一个从本机代码生成的警告。大多数小作业使用此NativeContainer分配类型。
Allocator.Persistent是最慢的分配,但只要你需要它,并且如果有必要,可以持续整个应用程序的生命周期。
它是直接调用malloc的包装器。较长的作业可以使用此NativeContainer分配类型。在性能至关重要的情况下,不应使用Persistent。
For example:
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
注意:上例中的number 1表示NativeArray的大小。 在这种情况下,它只有一个数组元素(因为它只在结果中存储一个数据)。
来自:https://docs.unity3d.com/Manual/JobSystemNativeContainer.html