序:昨天去了南京的汤山紫清湖温泉,安利一下,价格也不贵(不是打广告。。。不贴怎么订票之类的,有兴趣可以评论),还去见了多年未见的老友啊~不出意外的话下篇是手游客户端的性能篇(二)----Unity和C#版,想写优化和性能想写很久了,正好借机会总结一下。
先放一下2018年TX移动游戏技术评审标准:(摘自腾讯游戏学院)
1.foreach的GC问题(我在Unity 5.3.2.f1上测试还是有的)
eg:以下这几种使用方法都是有GC的(例子里定义了Vehicle类,它代表着所有的自定义和非自定义类型):
foreach(Vehicle car in vehicleList)
{
}
foreach(KeyValuePair<int, Vehicle> pair in vehicleDic)
{
}
foreach(Vehicle car in vehicleDic.Values)
{
}
总结:使用Foreach对数组不会有GC,但是Foreach对Dic和List都有GC。
再看看下面这种情况:
(一)
IEnumerator iter = vehicleDic.GetEnumerator();
while (iter.MoveNext())
{
}
(二)
var varIter = vehicleDic.GetEnumerator();
while (varIter.MoveNext())
{
}
(三)
using (var varIter = peopleDictionary.GetEnumerator())
{
while (varIter.MoveNext())
{
}
}
用profile查看后我们惊奇的发现(一)(三)的仍然有GC,(二)没有GC。
为什么呢???
使用ILSPY反编译可以看待IL代码,下面揭开谜底:
反编译-〉C#:
编译前:
foreach(KeyValuePair<int, Vehicle> pair in vehicleDic)
{
}
编译后:
using (Dictionary<int, Vehicle>.Enumerator iter= this.vehicleDic.GetEnumerator())
{
while (iter.MoveNext())
{
}
}
再对比一下while没有GC的情况:
var varIter = vehicleDic.GetEnumerator();
while (varIter.MoveNext())
{
}
对比,是不是说没有用var就没有GC呢?其实不然,因为你会发现两种情况基本没有区别,区别只在于使用using后会立即调用GC,而后面这种等系统来调用。所以只是看上去!只是看上去最后这种没有GC。
产生GC的真正原因:
GetEnumerator()返回的是值类型,而在中间层代码会转换为引用类型,造成装箱(后面文章会介绍装箱和拆箱),导致GC。到所以我们应该怎么写?
var varIter = vehicleDic.GetEnumerator();
while (varIter.MoveNext())
{
}
正确写法如上,虽然也会产生GC,但是不会立即调用,会等到系统触发调用,也就不容易造成卡帧。
(真正理解这些点,才可以更好的优化性能,提高性能,下篇再见!大家有喜欢的点个赞,写个评论,欢迎拍砖,欢迎一起探讨。套用抖音上的话,你们给已经有那么多粉丝的人点赞没有用的!给我点,我会把你们的文章都看一遍!把你们的评论都认真回复一遍!hhh)