牛骨文教育服务平台(让学习变的简单)
博文笔记

Unity的优化系列3 - 理解数组、 列表和字典的详细

创建时间:2016-05-28 投稿人: 浏览次数:163

孙广东  2016.5.24

      

集合的影响有哪些?

难道应该完全停止使用字典集合么?

总之,几毫秒的缓慢循环都会让玩家发疯!!!(集合都太慢了)   其实在游戏开发中经常会遇到对集合数据的排序:

在应用程序中我们管理相关对象通过以下两种方式之一:

  1. 通过创建对象数组(创建就不变大小)
  2. 通过创建对象的集合(可以动态改变大小)


每一种集合都有特定的用途,都有自己的优点和缺点。

List<GameObject> myListOfGameObjects = new List<GameObject>();

Dictionary<int, String> myDictionary = new Dictionary<int, String>();

新建一个脚本 作为测试:

public class GenericCollectionsTest : MonoBehaviour
{

    #region PUBLIC_DECLARATIONS

    public int numberOfIterations = 10000000;

    #endregion

    #region PRIVATE_DECLARATIONS

    private Stopwatch stopWatch;
  
    private List<int> intList;                 // 整数列表
    private Dictionary<int,int> intDictionary;    // 一本字典,键和值为整数。
    private int[] intArray;                     // 一个整数数组

    #endregion

    #region UNITY_CALLBACKS

    void Start()
    {
        stopWatch = new Stopwatch();
        intArray = new int[numberOfIterations];
        intList = new List<int>();
        intDictionary = new Dictionary<int, int>();

        AddFakeValuesInArray(numberOfIterations);
        AddFakeValuesInList(numberOfIterations);
        AddFakeValuesInDictionay(numberOfIterations);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            PerformTest();
        }

        if (Input.GetKeyDown(KeyCode.S))
        {
            SearchInList(111);
            SearchInDictionary(numberOfIterations - 1);
            UnityEngine.Debug.Log("SearchComplete");
        }
    }

    #endregion

    #region PRIVATE_METHODS

    private void AddFakeValuesInArray(int iterations)
    {
        for (int i = 0; i < iterations; i++)
        {
            intArray[i] = Random.Range(0, 100);
        }
    }

    private void AddFakeValuesInList(int iterations)
    {
        for (int i = 0; i < iterations; i++)
        {
            intList.Add(Random.Range(0, 100));
        }
        intList[iterations - 1] = 111;
    }


    private void AddFakeValuesInDictionay(int iterations)
    {
        for (int i = 0; i < iterations; i++)
        {
            intDictionary.Add(i, Random.Range(0, 100));
        }
        intDictionary[iterations - 1] = 111;
    }

    private void SearchInList(int value)
    {
        #region FIND_IN_LIST
        stopWatch.Start();
        int index = intList.FindIndex(item => item == value);

        stopWatch.Stop();
        UnityEngine.Debug.Log("Index " + index);
        UnityEngine.Debug.Log(“Time Taken to Find in List  ”+stopWatch.ElapsedMilliseconds+” ms”);
        stopWatch.Reset();
        #endregion

        #region CHECK_IF_CONTAINS_VALUE_IN_LIST
        stopWatch.Start();
        bool containsValue = intList.Contains(value);

        stopWatch.Stop();
        UnityEngine.Debug.Log(containsValue);
        UnityEngine.Debug.Log(“Time Taken To Check in List ”+stopWatch.ElapsedMilliseconds+” ms”);
        stopWatch.Reset();
        #endregion
    }

    private void SearchInDictionary(int key)
    {
        #region FIND_IN_DICTIONARY_USING_REQUIRED_KEY
        stopWatch.Start();
        int value = intDictionary[key];
        stopWatch.Stop();
        UnityEngine.Debug.Log((“Time Taken to Find in Dictionary   ”+stopWatch.ElapsedMilliseconds+” ms”);
        stopWatch.Reset();
        #endregion

        #region CHECK_IF_DICTIONARY_CONTAINS_VALUE
        stopWatch.Start();
        bool containsKey = intDictionary.ContainsKey(key);

        stopWatch.Stop();
        UnityEngine.Debug.Log(containsKey);
        UnityEngine.Debug.Log("Time taken to check if it contains key in Dictionary" + stopWatch.ElapsedMilliseconds+ “ ms”);
        stopWatch.Reset();
        #endregion
    }

    private void PerformTest()
    {
        
        #region ARRAY_ITERATION        // 循环遍历数组
        stopWatch.Start();

        for (int i = 0; i < intArray.Length; i++)
        {

        }

        stopWatch.Stop();
        UnityEngine.Debug.Log(“Time Taken By Array ”+stopWatch.ElapsedMilliseconds+ ”ms”);
        stopWatch.Reset();

        #endregion

        #region LIST_ITERATION            //  循环遍历列表中使用简单的 for 循环
        stopWatch.Start();
        for (int i = 0; i < intList.Count; i++)
        {

        }
        stopWatch.Stop();
        UnityEngine.Debug.Log(“Time Taken By List ”+stopWatch.ElapsedMilliseconds+ ”ms”);
        stopWatch.Reset();
        #endregion

        #region LIST_ITERATION_BY_FOREACH_LOOP             //  遍历列表中通过使用 foreach 循环
        stopWatch.Start();
        foreach (var item in intList)
        {
            
        }
        stopWatch.Stop();
        UnityEngine.Debug.Log(“Time Taken By List Using foreach  ”+stopWatch.ElapsedMilliseconds+ ”ms”);
        stopWatch.Reset();
        #endregion

        #region DICTIONARY_ITERATIOn_LOOP                //  遍历字典
        stopWatch.Start();

        foreach (var key in intDictionary.Keys)
        {

        }
        stopWatch.Stop();
        UnityEngine.Debug.Log(“Time Taken By Dictionary ”+stopWatch.ElapsedMilliseconds+ ”ms”);
        stopWatch.Reset();
        #endregion
    }
    #endregion
}

关于秒表类Stopwatch   ,用于测试函数的执行时间特别方便。    请参阅以下链接 ︰ http://www.dotnetperls.com/stopwatch (注意这个类是官方的API


运行之后的输出如下:



                 让我们来了解数据结构,我们应该使用 考虑的几例


案例 1) 对象的数量保持不变在整个游戏


       显然不会改变对象的数目 现在在这里就不值得用作列表或字典。


       在这里数组的性能列表2


案例 2) 对象的数量在游戏过程中不断变化


       显而易见的选择是列表。作为对象不停地变化,它是字典更快.      如果对象池,列出了常用来管理池。


列表与词典进行比较几乎是8-10 倍快如果您遍历使用foreach循环List 几乎才会 3 倍的时间比正常的循环,从而增加了使用foreach循环的一个更多缺点上面的示例所示。如果你想要看看其他缺点的foreach循环


难道我应该完全停止使用的词典吗?


字典的查找 索引可是强项:


SearchInList()方法的第一部分是来查找列表中传递给它的值,检查如果它实际上包含的值,并返回布尔值


 SeatchInDictionary()方法的第一部分是要根据传递给它,键的值和第二部分将检查如果该方法具有特定键或不存在,通过使用ContainsKey() 再次按键调用这些方法的


在看Log的输出:



              所以从图片显而易见的结论是,字典搜索时间是几乎为零。 所以每当要不断寻找一些对象在整个游戏的情况下,明智的选择就是选择词典!


            结论是简单的有三个基本准则 ︰


  1. 当对象数目仍然相同,也有是没有要求的密集搜索不使用列表。
  2. 如果对象是动态和搜索不是一个优先事项,列表!
  3. 快速访问和对象,那么词典将是明智的选择


你也可以通过以下链接以获取更多的深入研究,相同的 ︰ http://www.dotnetperls.com/dictionary-time   http://answers.unity3d.com/questions/38479/is-listt-as-fast-to-access-as-a-standard-array.html


 


声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。