关于网上讨论Foreach循环会不会产生GC的问题,不如自己实验一番,我用的Unity版本是2021.3.23f1c1版本。
测试代码如下:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
namespace Test
{
public class MyGCTest : MonoBehaviour
{
Dictionary<int, float> dic1 = new Dictionary<int, float>()
{
{ 0, 0.2f },
{ 100, 100.0f }
};
Dictionary<int, int> dic2 = new Dictionary<int, int>()
{
{ 0, 0 },
{ 100, 100 }
};
Dictionary<int, string> dic3 = new Dictionary<int, string>()
{
{ 0, "0.2f" },
{ 100, "100.0f" }
};
Dictionary<string, int> dic4 = new Dictionary<string, int>()
{
{ "0", 0 },
{ "100", 100 }
};
List<int> list1 = new List<int>() { 0, 1, 0 };
List<bool> list4 = new List<bool>() { false, true, false };
List<char> list5 = new List<char>() { 'f', 'a', 'b' };
List<string> list3 = new List<string>() { "6", "2", "3" };
List<TestClass> list2 = new List<TestClass>() { new TestClass("6"), new TestClass("2"), new TestClass("3") };
List<TestClass2> list6 = new List<TestClass2>() { new TestClass2(6), new TestClass2(2), new TestClass2(3) };
int[] arr1 = new int[3] { 0, 1, 0 };
bool[] arr2 = new bool[3] { false, true, false };
char[] arr3 = new char[3] { 'f', 'a', 'b' };
string[] arr4 = new string[3] { "6", "2", "3" };
TestClass[] arr5 = new TestClass[3] { new TestClass("6"), new TestClass("2"), new TestClass("3") };
void Update()
{
//----------------------字典-----------------
Profiler.BeginSample("ForeachGC.dic1");
foreach (var x in dic1)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.dic2");
foreach (var x in dic2)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.dic3");
foreach (var x in dic3)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.dic4");
foreach (var x in dic4)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.dic1第二次调用");
foreach (var x in dic1)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.dic1.Values");
foreach (var x in dic1.Values)
{
}
Profiler.EndSample();
//----------------------列表-----------------
Profiler.BeginSample("ForeachGC.list1");
foreach (var x in list1)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.list2");
foreach (var x in list2)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.list3");
foreach (var x in list3)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.list4");
foreach (var x in list4)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.list5");
foreach (var x in list5)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.list6");
foreach (var x in list6)
{
}
Profiler.EndSample();
//----------------------数组-----------------
Profiler.BeginSample("ForeachGC.arr1");
foreach (var x in arr1)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.arr2");
foreach (var x in arr2)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.arr3");
foreach (var x in arr3)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.arr4");
foreach (var x in arr4)
{
}
Profiler.EndSample();
Profiler.BeginSample("ForeachGC.arr5");
foreach (var x in arr5)
{
}
Profiler.EndSample();
}
}
public class TestClass
{
private string sd2;
public TestClass(string sd)
{
sd2 = sd;
}
}
public class TestClass2
{
private int sd2;
public TestClass2(int sd)
{
sd2 = sd;
}
}
}
第一帧产生GC;
第二帧不产生GC
后面都不产生GC
结论如下:
- 不同键值字典对的字典第一帧会产生48B的GC,键值对相同的字典只会产生一次GC;
- 遍历字典的Value会产生120BGC
- 遍历数组均不会产生GC
- 遍历List时,值类型会在首帧产生48BGC,引用类型不会产生GC