C# for、while和foreach遍历产生GC

最近在网上看到了有关于Foreach遍历会产生GC的文章今天测试了下,在这里记录下怕忘记。

先上测试代码

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class People
{
    public string Name;
    public int Age;
}
public class FontTextureSet : MonoBehaviour
{
    int[] tempsInts = new[] { 1, 3, 4, 5, 6 };
    private People[] peoples;
    private List<People> peoplesList;
    private List<int> intList; 
    private Dictionary<int, People> peopleDictionary;
    private Dictionary<int, int> intDictionary; 
    private int tem;
	// Use this for initialization
    void Awake()
    {
        peoples = new People[5];
        peoplesList = new List<People>();
        intList = new List<int>();
        peopleDictionary = new Dictionary<int, People>();
        intDictionary = new Dictionary<int, int>();
        for (int i = 0; i < 5; i++)
        {
            People people = new People();
            people.Age = i;
            people.Name = ((char) 'A' + i).ToString();
            peoples[i] = people;
            peoplesList.Add(people);
            peopleDictionary.Add(i, people);
            intDictionary.Add(i,i);
            intList.Add(i);
        }
	}

    void Update()
    {
        Profiler.BeginSample("Foreach Int Array");
        foreach (int v in tempsInts)
        {
            tem = v;
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach People Array");
        foreach (People p in peoples)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foeach Int List");
        foreach (int i in intList)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach People List");
        foreach (People people in peoplesList)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach People Dictionary");
        foreach (KeyValuePair<int, People> keyValuePair in peopleDictionary)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foeach peopleDictionary.Values");
        foreach (People people in peopleDictionary.Values)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach Int Dictionary");
        foreach (KeyValuePair<int, int> keyValuePair in intDictionary)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach intDictionary.Values");
        foreach (int value in intDictionary.Values)
        {
            
        }
        Profiler.EndSample();
    }
}
ok,在来看看GC情况


哦 my god 这是真的吗,除了数组的遍历其他都产生了GC,这要是真的在Update里用了foreach遍历Directionary和List那不是要疯了,这代码要是让主程看到他肯定要哭,好吧,废话不多说,先来分析一下结果:

1、就是foreach变量数组不会产生GC,遍历Directionary和List都会产生GC

2、foreach遍历List产生GC是24B,Directionary是28B,注意Directionary遍历有多种这里我只测试了两种用foreach的遍历方法,有Directionary.Values遍历会产生40B的GC

3、GC的产生与数据类型无关,与数据结构有关


接下来能是for和while其实他们两差不多在遍历Directionary时都会产生GC,有一种情况除外,先来看测试代码

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class People
{
    public string Name;
    public int Age;
}
public class FontTextureSet : MonoBehaviour
{
    int[] tempsInts = new[] { 1, 3, 4, 5, 6 };
    private People[] peoples;
    private List<People> peoplesList;
    private List<int> intList; 
    private Dictionary<int, People> peopleDictionary;
    private Dictionary<int, int> intDictionary; 
    private int tem;
	// Use this for initialization
    void Awake()
    {
        peoples = new People[5];
        peoplesList = new List<People>();
        intList = new List<int>();
        peopleDictionary = new Dictionary<int, People>();
        intDictionary = new Dictionary<int, int>();
        for (int i = 0; i < 5; i++)
        {
            People people = new People();
            people.Age = i;
            people.Name = ((char) 'A' + i).ToString();
            peoples[i] = people;
            peoplesList.Add(people);
            peopleDictionary.Add(i, people);
            intDictionary.Add(i,i);
            intList.Add(i);
        }
	}

    void Update()
    {
        Profiler.BeginSample("For Int Array");
        for (int i = 0; i < tempsInts.Length; i++)
        {
            //tempsInts[i];
        }
        Profiler.EndSample();

        Profiler.BeginSample("For People Array");
        for (int i=0; i<peoples.Length; i++)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("For Int List");
        for (int i=0; i< intList.Count; i++)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("For People List");
        for (int i=0; i<peoplesList.Count; i++)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("For People Dictionary.Values");
        for (int i =0;i<peopleDictionary.Values.Count; i++)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("For peopleDictionary");
        IEnumerator e = peopleDictionary.GetEnumerator();
        e.MoveNext();
        for (int i=0; i<peopleDictionary.Count; e.MoveNext(), i++)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("While Dictionary");
        IEnumerator enumerator = peopleDictionary.GetEnumerator();
        //e.MoveNext();
        while (e.MoveNext())
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("While List");
        int num = 0;
        while (num < peoplesList.Count)
        {
            num++;
        }
        Profiler.EndSample();
    }
}

结果图如下:


结论:

1、Dictionary不管是for、while还是foreach都会产生GC都是28B(注意这里没有用var这个关键字,下面我会对用var的遍历做测试)

2、For遍历Dictionary.Values产生的GC是72B,比foreach多32B

3、For和while遍历数组和List都不会产生GC


上面我提到了var这个关键字,ok,下面我们就对这个做个测试

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class People
{
    public string Name;
    public int Age;
}
public class FontTextureSet : MonoBehaviour
{
    int[] tempsInts = new[] { 1, 3, 4, 5, 6 };
    private People[] peoples;
    private List<People> peoplesList;
    private List<int> intList; 
    private Dictionary<int, People> peopleDictionary;
    private Dictionary<int, int> intDictionary; 
    private int tem;
	// Use this for initialization
    void Awake()
    {
        peoples = new People[5];
        peoplesList = new List<People>();
        intList = new List<int>();
        peopleDictionary = new Dictionary<int, People>();
        intDictionary = new Dictionary<int, int>();
        for (int i = 0; i < 5; i++)
        {
            People people = new People();
            people.Age = i;
            people.Name = ((char) 'A' + i).ToString();
            peoples[i] = people;
            peoplesList.Add(people);
            peopleDictionary.Add(i, people);
            intDictionary.Add(i,i);
            intList.Add(i);
        }
	}

    void Update()
    {
        Profiler.BeginSample("Foreach Var Dictionary");
        foreach (var VARIABLE in peopleDictionary)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach Var Dictionary.Values");
        foreach (var value in peopleDictionary.Values)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach Var List");
        foreach (var people in peoplesList)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("For Var Dictionary");
        var e = peopleDictionary.GetEnumerator();
        e.MoveNext();
        for (int i=0; i<peopleDictionary.Count; e.MoveNext(), i++)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("While Var Dictionary");
        var enumerator = peopleDictionary.GetEnumerator();
        //e.MoveNext();
        while (e.MoveNext())
        {
            
        }
        Profiler.EndSample();
    }
}
结果如下图所示:

可以看出对于foreach来说没什么变化,但对for和while来说意义非凡啊,Directionary的遍历没有GC了。

OK,最后来做个总结:

1、遍历不要用foreach,全用for和while

2、遍历Dictionary是有一下两种方式的一种:

        var e = peopleDictionary.GetEnumerator();
        e.MoveNext();
        for (int i=0; i<peopleDictionary.Count; e.MoveNext(), i++)
        {
            
        }
        

        
        var enumerator = peopleDictionary.GetEnumerator();
        //e.MoveNext();
        while (e.MoveNext())
        {
            
        }
        
    }

以上的测试只是简单测试不全,但已经达到目的了:就是以后遍历怎么遍历不会产生GC。Ok,今天就这么多,最后还有疑问,就是他们怎么产生GC的,有些为什么又没有GC? 哪位大神知道,求告知,谢谢!!!!!!

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值