在 Unity3D 中用于优化的最快集合?

Fastest Collection to Use for Optimization in Unity3D?

我正在阅读有关内置数组和列表等集合的不同之处,并注意到内置数组比列表快很多(在某些情况下快 7 倍)。

所以我的问题是,如果我使用内置数组,我没有完全填充而是有一个最大值,并使用一个计数器 int 来跟踪大小,它会显着吗比使用列表更快?

重要的原因是我有一个多人游戏,我在 Node.js 中从头开始为自己构建服务器,并使用 websockets-sharp 作为客户端的库,并且我看到了一些由于我必须修改和检查我的更新函数(使用列表、堆栈、字典和队列)的集合而滞后,我想知道 byte[] 数组会提高性能。

P.S。这是我从有关内置阵列性能与 System.Collections:

获得信息的地方

http://answers.unity3d.com/questions/38479/is-listt-as-fast-to-access-as-a-standard-array.html

Performance differences... so dramatic?

http://wiki.unity3d.com/index.php/Choosing_the_right_collection_type

在数组和列表之间的功能重叠中,通过包装数组实现的列表意味着我们几乎总是期望数组更快,而且在考虑直接访问数组可能允许一些编译器和抖动之前优化也是如此。

就是说,如果您要执行列表提供而数组没有的操作,您现在还有更多工作要做。如果您这样做的效率不如列表中的代码,那么您只会让事情变得更慢。即使做得很完美,您也可能会无法使用让抖动跳过边界检查的代码(例如,因为您在数组末尾留下了一些 space),这意味着实际性能不如基准测试抖动可以做到这一点)。

当涉及到字典时更是如此,您还提到它因为数组不提供相同的 hash-based O(1) 查找。

真的,为了性能从列表切换到数组你想研究 List 的代码(源是可用的)了解成本在哪里,然后考虑这些成本如何影响你的给定用法。这将指导转换将在何处获得、失去、中断或只是浪费时间。

If I use built in arrays that I do not fill completely but instead have a max value, and use a counter int to keep track of the size, will it be significantly faster than using Lists?

我过去曾用 Unity 做过实验,这样做对于需要在每一帧上循环的大量项目(例如图像处理)完全没问题。

我曾经制作过一个通过网络流式传输 HQ 图像的应用程序。使用 List 很容易制作,但在我切换到 Array 后,我每秒接收的帧数增加了。 它也搭上了内存分配

使用 Array 的唯一缺点是您必须分配大量内存以确保它足以容纳您的项目。您还必须检查要放入数组的当前项目是否适合。如果没有,您必须创建更大的新数组,然后将旧数据复制到新数据。

Unity 的 blog 也有一个 post 显示使用 ArrayList 改进 Update() 函数的性能差异。 这确实是一个很大的性能提升,在那个实验 中,数组比 List 快了大约 5x

这些是我在使用 Unity 时为自己设定的规则,即使在今天它仍然是真实的:

1。如果您需要存储大型项目(200k 及以上),需要您在每一帧中循环遍历它们,请使用数组和一个简单的 int 值,您可以使用它来确定数组的长度。

2。如果这只是 5,000 和 运行 大小的项目,那么使用 List.

我在 Unity 中将 this 代码修改为 运行,结果如下。

Array/for: 6726ms (-1295415896)

List/for: 15803ms (-1295415896)

Array/foreach: 8511ms (-1295415896)

List/foreach: 42689ms (-1295415896)

与普通的 C# 应用程序不同,Unity 中的区别非常重要。

void Start()
{
    List<int> list = new List<int>(6000000);
    for (int i = 0; i < 6000000; i++)
    {
        list.Add(UnityEngine.Random.Range(1, 10));
    }
    int[] arr = list.ToArray();

    int chk = 0;
    Stopwatch watch = Stopwatch.StartNew();
    for (int rpt = 0; rpt < 100; rpt++)
    {
        int len = list.Count;
        for (int i = 0; i < len; i++)
        {
            chk += list[i];
        }
    }
    watch.Stop();
    UnityEngine.Debug.Log(String.Format("List/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk));

    chk = 0;
    watch = Stopwatch.StartNew();
    for (int rpt = 0; rpt < 100; rpt++)
    {
        int len = arr.Length;
        for (int i = 0; i < len; i++)
        {
            chk += arr[i];
        }
    }
    watch.Stop();
    UnityEngine.Debug.Log(String.Format("Array/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk));

    chk = 0;
    watch = Stopwatch.StartNew();
    for (int rpt = 0; rpt < 100; rpt++)
    {
        foreach (int i in list)
        {
            chk += i;
        }
    }
    watch.Stop();
    UnityEngine.Debug.Log(String.Format("List/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk));

    chk = 0;
    watch = Stopwatch.StartNew();
    for (int rpt = 0; rpt < 100; rpt++)
    {
        foreach (int i in arr)
        {
            chk += i;
        }
    }
    watch.Stop();
    UnityEngine.Debug.Log(String.Format("Array/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk));
}