Unity Job System详解(3)——NativeList源码分析

【前言】

查看NativeList源码需要安装Unity的Entities Package

NativeList要实现的基本功能类似C# List,如下:

(一些简单的类同NativeArray的不在说明)

构造函数、析构函数、取值赋值

扩容、添加、移除操作

解析步骤包括,基本函数,常用操作,常用属性,接口函数

【源码分析】

定义

//一个泛型结构体,且是unsafe的,继承了三个接口,并要求泛型是非托管类型的,如果T是引用类型的会报错
public unsafe struct NativeList<T> : INativeDisposable, INativeList<T>, IIndexable<T> where T : unmanaged
{

}

构造函数 

        public NativeList(AllocatorManager.AllocatorHandle allocator)
            : this(1, allocator)
        {
        }

        public NativeList(int initialCapacity, AllocatorManager.AllocatorHandle allocator)
        {
            this = default;
            AllocatorManager.AllocatorHandle temp = allocator;
            Initialize(initialCapacity, ref temp);
        }

        internal void Initialize<U>(int initialCapacity, ref U allocator) where U : unmanaged, AllocatorManager.IAllocator
        {
            var totalSize = sizeof(T) * (long)initialCapacity; //sizeof用于计算值类型对象所占用的内存大小,与容量相乘,得到初始化需要的内存大小
            m_ListData = UnsafeList<T>.Create(initialCapacity, ref allocator, NativeArrayOptions.UninitializedMemory);//listData是当前结构体的字段,调用UnsafeList的静态方法创建
        }

        //数据所在
        [NativeDisableUnsafePtrRestriction]//该特性允许使用指针
        internal UnsafeList<T>* m_ListData;//指向数据的指针

 接着看UnsafeList

//同NativeList一样
public unsafe struct UnsafeList<T> : INativeDisposable, INativeList<T>, IIndexable<T> where T : unmanaged
{
}

 直接看Create方法

        internal static UnsafeList<T>* Create<U>(int initialCapacity, ref U allocator, NativeArrayOptions options) where U : unmanaged, AllocatorManager.IAllocator
        {
            UnsafeList<T>* listData = allocator.Allocate(default(UnsafeList<T>), 1);//通过Allocator分配内存,返回该内存起始地址的指针  NativeArrayOptions有两个选择ClearMemory、UninitializedMemory
            *listData = new UnsafeList<T>(initialCapacity, allocator.Handle, options);//构造函数返回新的内存起始地址的指针
            return listData;
        }

        public UnsafeList(int initialCapacity, AllocatorManager.AllocatorHandle allocator, NativeArrayOptions options = NativeArrayOptions.UninitializedMemory)
    {
        Ptr = null;//数据所在
        m_length = 0;//length和capacity分别类似于C# List的count和capacity
        m_capacity = 0;
        Allocator = allocator;
        padding = 0;

        SetCapacity(math.max(initialCapacity, 1));

        if (options == NativeArrayOptions.ClearMemory && Ptr != null)
        {
            var sizeOf = sizeof(T);
            UnsafeUtility.MemClear(Ptr, Capacity * sizeOf);//ClearMemory选项会清空已有的内存,本质是调用memset,将从ptr开始,长度为Capacity * sizeOf的内存的值设置为0
        }
    }

进一步看SetCapacity方法 

        public void SetCapacity(int capacity)
        {
            SetCapacity(ref Allocator, capacity);
        }

        void SetCapacity<U>(ref U allocator, int capacity) where U : unmanaged, AllocatorManager.IAllocator
        {
            CollectionHelper.CheckCapacityInRange(capacity, Length);//先检查设置的容量是否大于长度

            var sizeOf = sizeof(T);//获取T类型占用的字节数
            //CacheLineSize是当前平台的L1缓存行。L1缓存是离CPU最近的缓存层级,也是访问速度最快的缓存。它由数据缓存和指令缓存组成,分别用于存储数据和指令。缓存行是缓存的最小读写单位,一般是以字节为单位。
            //L1缓存行的大小在不同的处理器架构上可能会有所不同,常见的大小是64字节。当CPU需要读取或写入数据时,它会首先检查L1缓存,如果所需数据在缓存行中,则可以直接访问,从而加快数据访问速度。如果数据不在缓存行中,则需要从更慢的内存层次(如L2缓存或主存)中获取。
            //L1缓存行的设计目的是通过提前将数据和指令加载到高速缓存中,减少CPU等待数据的时间,从而提高计算机的性能。
            var newCapacity = math.max(capacity, CollectionHelper.CacheLineSize / sizeO
### Unity Job System 详细介绍 #### 多核处理能力的利用 Unity Job System 提供了一种有效的方法来利用现代计算机中的多核处理器,从而显著提升应用程序性能[^1]。传统单线程编程模型无法充分发挥硬件潜力,而Job System允许开发者编写可并行执行的任务。 #### 编程模式与挑战 采用Job System意味着要适应全新的编程范式。这不仅涉及学习新API,还需要重新思考算法设计方式以最大化并发优势。例如,在处理复杂逻辑时需考虑任务划分、同步机制等问题[^2]。 #### 性能优化实践 为了验证Job System带来的性能增益,可以通过Unity Profiler工具对比启用前后的情况。具体做法是在关键代码段添加Profiler Marker标签,之后观察图表中显示的时间消耗差异[^3]。 ### 使用教程 #### 基本概念介绍 - **Job**: 表示一个独立的工作单元,可以在不同CPU核心上同时运行。 - **NativeArray<T>**: 特殊的数据结构用于安全地共享数据给Jobs访问而不造成GC压力[^5]。 #### 示例代码展示 下面是一个简单例子展示了如何定义和调度job: ```csharp using UnityEngine; using Unity.Jobs; public class Example : MonoBehaviour { struct MyJob : IJob { // 定义作业类型 public float a; public float b; public void Execute() { Debug.Log(a * b); } } private void Start(){ var myJob = new MyJob{ a = 10f, b = 20f }; JobHandle handle = myJob.Schedule(); // 调度作业 handle.Complete(); // 等待完成 } } ``` 对于更复杂的场景,则可能涉及到多个jobs之间的协调工作以及对`NativeCollection`类型的运用等高级话题[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值