手遊客戶端的效能篇(一)----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)