最近在网上看到了有关于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 peoplesList;
private List intList;
private Dictionary peopleDictionary;
private Dictionary intDictionary;
private int tem;
// Use this for initialization
void Awake()
{
peoples = new People[5];
peoplesList = new List();
intList = new List();
peopleDictionary = new Dictionary();
intDictionary = new Dictionary();
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 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 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 peoplesList;
private List intList;
private Dictionary peopleDictionary;
private Dictionary intDictionary;
private int tem;
// Use this for initialization
void Awake()
{
peoples = new People[5];
peoplesList = new List();
intList = new List();
peopleDictionary = new Dictionary();
intDictionary = new Dictionary();
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
结论:
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 peoplesList;
private List intList;
private Dictionary peopleDictionary;
private Dictionary intDictionary;
private int tem;
// Use this for initialization
void Awake()
{
peoples = new People[5];
peoplesList = new List();
intList = new List();
peopleDictionary = new Dictionary();
intDictionary = new Dictionary();
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
结果如下图所示:
可以看出对于foreach来说没什么变化,但对for和while来说意义非凡啊,Directionary的遍历没有GC了。
OK,最后来做个总结:
1、遍历不要用foreach,全用for和while
2、遍历Dictionary是有一下两种方式的一种:
var e = peopleDictionary.GetEnumerator();
e.MoveNext();
for (int i=0; i