手游客户端的性能篇(一)----Unity和C#版之Foreach GC

          序:昨天去了南京的汤山紫清湖温泉,安利一下,价格也不贵(不是打广告。。。不贴怎么订票之类的,有兴趣可以评论),还去见了多年未见的老友啊~不出意外的话下篇是手游客户端的性能篇(二)----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)

猜你喜欢

转载自blog.csdn.net/jfy307596479/article/details/83992439
今日推荐